go-gorm/gorm · error · ErrUnsupportedDataType

unsupported data type: %+v

Error message

unsupported data type: %+v

What it means

ParseWithSpecialTableName rejects a nil destination outright with the ErrUnsupportedDataType sentinel wrapped around the value. Passing a nil model (typed nil pointers included, since dest == nil only catches truly nil interface) means GORM has nothing to reflect on. The error is wrapped with %w so errors.Is(err, schema.ErrUnsupportedDataType) works.

Source

Thrown at schema/schema.go:141

}

var callbackTypes = []callbackType{
	callbackTypeBeforeCreate, callbackTypeAfterCreate,
	callbackTypeBeforeUpdate, callbackTypeAfterUpdate,
	callbackTypeBeforeSave, callbackTypeAfterSave,
	callbackTypeBeforeDelete, callbackTypeAfterDelete,
	callbackTypeAfterFind,
}

// Parse get data type from dialector
func Parse(dest interface{}, cacheStore *sync.Map, namer Namer) (*Schema, error) {
	return ParseWithSpecialTableName(dest, cacheStore, namer, "")
}

// ParseWithSpecialTableName get data type from dialector with extra schema table
func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Namer, specialTableName string) (*Schema, error) {
	if dest == nil {
		return nil, fmt.Errorf("%w: %+v", ErrUnsupportedDataType, dest)
	}

	modelType := reflect.ValueOf(dest).Type()
	if modelType.Kind() == reflect.Ptr {
		modelType = modelType.Elem()
	}

	if modelType.Kind() != reflect.Struct {
		if modelType.Kind() == reflect.Interface {
			modelType = reflect.Indirect(reflect.ValueOf(dest)).Elem().Type()
		}

		for modelType.Kind() == reflect.Slice || modelType.Kind() == reflect.Array || modelType.Kind() == reflect.Ptr {
			modelType = modelType.Elem()
		}

		if modelType.Kind() != reflect.Struct {
			if modelType.PkgPath() == "" {

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Initialize the model before passing: `var users []User; db.Find(&users)`.
  2. Guard call sites where the model may legitimately be nil and skip the GORM call.
  3. Check errors.Is(err, schema.ErrUnsupportedDataType) to give a clear message in wrappers.

Example fix

// before
var user *User // nil
err := db.First(user).Error

// after
var user User
err := db.First(&user).Error
Defensive patterns

Strategy: type-guard

Validate before calling

if dest == nil {
    return errors.New("model must not be nil")
}
// or: ensure pointer to initialized struct before calling GORM

Type guard

func isNonNilStructPtr(v any) bool {
    if v == nil { return false }
    rv := reflect.ValueOf(v)
    return rv.Kind() == reflect.Ptr && !rv.IsNil() && rv.Elem().Kind() == reflect.Struct
}

Try / catch

if err := db.AutoMigrate(model).Error; err != nil {
    if errors.Is(err, schema.ErrUnsupportedDataType) {
        return fmt.Errorf("model was nil or not a struct: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling db.AutoMigrate(nil), db.Find(nil), or passing a nil interface{} model variable — commonly a nil slice header or a model variable that was never initialized.

Common situations: Passing a nil pointer from optional request params; test helpers with unset model variables; reflection-driven code that passes a nil interface{} dynamically.

Related errors


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