go-gorm/gorm · error

model value required when using preload

Error message

model value required when using preload

What it means

The Preload callback requires a parsed schema to resolve relation names. If db.Statement.Schema is nil when Statement.Preloads is non-empty, GORM adds fmt.Errorf("%w when using preload", gorm.ErrModelValueRequired) - 'model value required when using preload'. This happens when the query was built without a model, most commonly via db.Table(...) or Raw SQL, because Table does not produce a schema.

Source

Thrown at callbacks/query.go:280

					})
				}
			}

			db.Statement.AddClause(fromClause)
		} else {
			db.Statement.AddClauseIfNotExists(clause.From{})
		}

		db.Statement.AddClauseIfNotExists(clauseSelect)

		db.Statement.Build(db.Statement.BuildClauses...)
	}
}

func Preload(db *gorm.DB) {
	if db.Error == nil && len(db.Statement.Preloads) > 0 {
		if db.Statement.Schema == nil {
			db.AddError(fmt.Errorf("%w when using preload", gorm.ErrModelValueRequired))
			return
		}

		joins := make([]string, 0, len(db.Statement.Joins))
		for _, join := range db.Statement.Joins {
			joins = append(joins, join.Name)
		}

		tx := preloadDB(db, db.Statement.ReflectValue, db.Statement.Dest)
		if tx.Error != nil {
			return
		}

		db.AddError(preloadEntryPoint(tx, joins, &tx.Statement.Schema.Relationships, db.Statement.Preloads, db.Statement.Preloads[clause.Associations]))
	}
}

func AfterQuery(db *gorm.DB) {

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Use db.Model(&User{}) instead of db.Table("users") when you need Preload.
  2. Or drop the Preload call and load the related data with explicit queries.
  3. For map destinations, Preload cannot work - switch to a typed model struct.
  4. Add a guard in helpers: if len(preloads) > 0 && model == nil, panic/return early with a clear message.

Example fix

// before
db.Table("users").Preload("Orders").Find(&users)

// after
db.Model(&User{}).Preload("Orders").Find(&users)
Defensive patterns

Strategy: validation

Validate before calling

func canPreload(tx *gorm.DB) bool {
    return tx.Statement != nil && tx.Statement.Schema != nil
}
// wrapper:
if len(preloads) > 0 && !canPreload(db) {
    return errors.New("Preload requires db.Model(&Struct{}), not Table/Raw")
}

Try / catch

if err := db.Table("users").Preload("Orders").Find(&users).Error; err != nil {
    if errors.Is(err, gorm.ErrModelValueRequired) {
        // rebuild with db.Model(&User{}) and retry
    }
    return err
}

Prevention

When it happens

Trigger: db.Table("users").Preload("Orders").Find(&users) - Table names the table but leaves Schema nil; or Preload chained onto a Session where the model was never set; Raw/SkipHooks flows that carry Preloads without a model.

Common situations: Migrating a query from db.Model(&User{}) to db.Table("users") for performance/unmapped columns and forgetting to drop the Preload; generic repository helpers that accept table names; scoping code that clears the model.

Related errors


AI-assisted analysis of go-gorm/gorm@1d6ce99528 (2026-08-15). Data as JSON: /api/errors/40dd71d0586d32fd. Report an issue: GitHub.