go-gorm/gorm · error

unsupported data type: Table not set, please set it like: db

Error message

unsupported data type: Table not set, please set it like: db.Model(&user) or db.Table("users")

What it means

In Execute's model parsing, when stmt.Parse(stmt.Model) fails with schema.ErrUnsupportedDataType AND the statement has no table (stmt.Table == "" and TableExpr == nil and SQL is empty), GORM wraps it as '%w: Table not set, please set it like: db.Model(&user) or db.Table("users")'. It tells you the Dest type cannot identify a table on its own and you did not supply one.

Source

Thrown at callbacks.go:113

	if db.DefaultContextTimeout > 0 {
		if _, ok := stmt.Context.Deadline(); !ok {
			stmt.Context, _ = context.WithTimeout(stmt.Context, db.DefaultContextTimeout)
		}
	}

	// assign model values
	if stmt.Model == nil {
		stmt.Model = stmt.Dest
	} else if stmt.Dest == nil {
		stmt.Dest = stmt.Model
	}

	// parse model values
	if stmt.Model != nil {
		if err := stmt.Parse(stmt.Model); err != nil && (!errors.Is(err, schema.ErrUnsupportedDataType) || (stmt.Table == "" && stmt.TableExpr == nil && stmt.SQL.Len() == 0)) {
			if errors.Is(err, schema.ErrUnsupportedDataType) && stmt.Table == "" && stmt.TableExpr == nil {
				db.AddError(fmt.Errorf("%w: Table not set, please set it like: db.Model(&user) or db.Table(\"users\")", err))
			} else {
				db.AddError(err)
			}
		}
	}

	// assign stmt.ReflectValue
	if stmt.Dest != nil {
		stmt.ReflectValue = reflect.ValueOf(stmt.Dest)
		for stmt.ReflectValue.Kind() == reflect.Ptr {
			if stmt.ReflectValue.IsNil() && stmt.ReflectValue.CanAddr() {
				stmt.ReflectValue.Set(reflect.New(stmt.ReflectValue.Type().Elem()))
			}

			stmt.ReflectValue = stmt.ReflectValue.Elem()
		}
		if !stmt.ReflectValue.IsValid() {
			db.AddError(ErrInvalidValue)

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Chain db.Model(&User{}) (or db.Table("users")) before the finisher.
  2. For Pluck-style reads of one column, use db.Model(&User{}).Pluck("id", &ids).
  3. For map destinations, always set db.Table("...") since maps have no schema.
  4. Check the call chain in stack traces for a missing Model between Session and Find.

Example fix

// before
var ids []int
db.Find(&ids) // unsupported data type: Table not set...

// after
var ids []int
db.Model(&User{}).Pluck("id", &ids)
Defensive patterns

Strategy: validation

Validate before calling

// guard finishers: non-struct dest requires Model or Table
func hasTableSource(tx *gorm.DB) bool {
    return tx.Statement != nil && (tx.Statement.Table != "" || tx.Statement.TableExpr != nil || tx.Statement.Model != nil)
}
// in a wrapper:
if !hasTableSource(db) && !isStructDest(dest) { return errors.New("set Model/Table") }

Type guard

func isStructDest(dest interface{}) bool {
    rv := reflect.Indirect(reflect.ValueOf(dest))
    if rv.Kind() == reflect.Slice { rv = reflect.Indirect(rv.Type().Elem()) }
    return rv.Kind() == reflect.Struct
}

Try / catch

if err := db.Find(&ids).Error; err != nil {
    if errors.Is(err, schema.ErrUnsupportedDataType) {
        return errors.New("table not set: chain Model/Table before Find")
    }
    return err
}

Prevention

When it happens

Trigger: Running a finisher where Dest is a non-struct scalar/container (e.g. db.Find(&ids) with ids []int, or db.Count(&n) without Model) and no db.Model(...) or db.Table(...) was chained, so parsing fails and there is no table to fall back on.

Common situations: Plucking into []int/[]string without Table/Model; db.Count without Model; Dest declared as map with no Table (map scanning requires Table); refactoring a method so the Model call was dropped; using raw struct-less queries after upgrading from GORM v1 behaviors.

Related errors


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