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
- Initialize the model before passing: `var users []User; db.Find(&users)`.
- Guard call sites where the model may legitimately be nil and skip the GORM call.
- 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
- Always pass &Model{} (never a nil variable) to AutoMigrate/Find.
- Check optional models for nil before DB calls.
- Match on the ErrUnsupportedDataType sentinel in wrappers.
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
- unsupported data type
- slice data #%v is invalid: unsupported data
- unsupported data type: %s.%s
- violates check constraint
- unsupported relationship
AI-assisted analysis of go-gorm/gorm@1d6ce99528 (2026-08-15).
Data as JSON: /api/errors/a7857974c09e11be.
Report an issue: GitHub.