Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/go-gorm/gorm/llms.txt

Use this file to discover all available pages before exploring further.

GORM stores the last error from an operation on db.Error. Use the standard errors.Is function to check for specific sentinel errors — this works correctly even when errors are wrapped.
result := db.First(&user, 100)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
    // record does not exist
}
All GORM errors are package-level var values, not types. Always use errors.Is rather than direct equality (==) so that wrapping is handled correctly.

Error reference

Message: record not foundOccurs when: First, Take, or Last is called and no record matches the conditions.How to handle:
var user User
if err := db.First(&user, "name = ?", "nobody").Error; err != nil {
    if errors.Is(err, gorm.ErrRecordNotFound) {
        // return 404 or a default value
    }
    // unexpected error
}
Find does not return this error when the result set is empty — it returns a nil error with RowsAffected == 0.
Message: invalid transactionOccurs when: Commit or Rollback is called on a *DB that is not inside an active transaction, or when Begin cannot start a transaction because the pool does not implement TxBeginner or ConnPoolBeginner.
tx := db.Begin()
if errors.Is(tx.Error, gorm.ErrInvalidTransaction) {
    // pool does not support transactions
}
Message: not implementedOccurs when: A dialector or migrator method is called that the driver has not implemented.
Message: WHERE conditions requiredOccurs when: An Update, Updates, or Delete is executed without any WHERE conditions and Config.AllowGlobalUpdate is false (the default).
// This will fail with ErrMissingWhereClause
db.Delete(&User{})

// Correct — add a condition
db.Where("age > ?", 18).Delete(&User{})

// Or explicitly allow global operations
db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
Message: unsupported relationsOccurs when: db.Association(column) is called with a field name that does not correspond to a known relationship on the model schema.
Message: primary key requiredOccurs when: An operation requires a primary key (e.g., FindInBatches pagination, or association operations) but the model has none defined or the value is zero.
Message: model value requiredOccurs when: A Model or target value is required for an operation but was not provided.
Message: model accessible fields requiredOccurs when: GORM cannot find any accessible (readable/writable) fields on the model, usually because the struct has no exported fields.
Message: sub query requiredOccurs when: A clause expects a subquery value (e.g., using *DB as a condition argument) but none was provided.
Message: unsupported dataOccurs when: A value passed to a GORM method is of a type that cannot be handled (e.g., an unsupported type in Select args).
Message: unsupported driverOccurs when: db.SavePoint or db.RollbackTo is called and the dialector does not implement SavePointerDialectorInterface.
Message: registeredOccurs when: db.Use(plugin) is called with a plugin whose Name() is already registered.
if err := db.Use(&MyPlugin{}); errors.Is(err, gorm.ErrRegistered) {
    // plugin is already loaded
}
Message: invalid fieldOccurs when: A referenced field name does not exist on the schema.
Message: empty slice foundOccurs when: An empty slice is passed to Create or a related operation that requires at least one element.
Message: dry run mode unsupportedOccurs when: Row() or Rows() is called while dry-run mode is active. Dry run can only generate SQL for operations that return a *DB; it cannot simulate raw row scanning.
Message: invalid dbOccurs when: db.DB() cannot resolve the underlying *sql.DB from the current connection pool — for example, when the pool is a custom type that does not implement GetDBConnector.
Message: invalid value, should be pointer to struct or sliceOccurs when: A non-pointer or otherwise unsuitable value is passed to a method that requires a pointer to a struct or slice (e.g., Association.Append with an un-addressable struct).
Message: invalid association values, length doesn't matchOccurs when: Association.Append or Association.Replace is called with a slice of values whose length does not match the number of parent records.
Message: preload is not allowed when count is usedOccurs when: Preload is combined with Count in the same query chain. Preloading makes no sense for a count query.
// This will fail
db.Preload("Orders").Count(&count)

// Correct — separate the count from the preload query
db.Model(&User{}).Count(&count)
Message: duplicated key not allowedOccurs when: A Create or Save violates a unique key constraint. Only returned when Config.TranslateError is true and the dialector implements ErrorTranslator.
result := db.Create(&user)
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
    // handle duplicate (e.g., return HTTP 409)
}
Message: violates foreign key constraintOccurs when: An insert or update violates a foreign key constraint. Only returned when Config.TranslateError is true and the dialector implements ErrorTranslator.
result := db.Create(&order) // where order.UserID does not exist
if errors.Is(result.Error, gorm.ErrForeignKeyViolated) {
    // handle referential integrity error
}
Message: violates check constraintOccurs when: An insert or update violates a CHECK constraint defined on the table. Only returned when Config.TranslateError is true and the dialector implements ErrorTranslator.
result := db.Create(&product) // where price < 0 violates CHECK (price >= 0)
if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) {
    // handle constraint violation
}

Error handling patterns

// ErrRecordNotFound — safe "not found" check
var user User
if err := db.First(&user, id).Error; err != nil {
    if errors.Is(err, gorm.ErrRecordNotFound) {
        return nil, fmt.Errorf("user %d not found", id)
    }
    return nil, fmt.Errorf("database error: %w", err)
}
Enable Config.TranslateError: true to convert raw driver errors into typed GORM sentinel errors. Without it, ErrDuplicatedKey, ErrForeignKeyViolated, and ErrCheckConstraintViolated are never returned — you receive the raw *pq.Error or equivalent.