{"record":{"id":"7dacdc5e20330086","repo":"go-gorm/gorm","slug":"slice-data-v-is-invalid-unsupported-data","errorCode":null,"errorMessage":"slice data #%v is invalid: unsupported data","messagePattern":"slice data #(.+?) is invalid: unsupported data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"callbacks/create.go","lineNumber":291,"sourceCode":"\t\t}\n\n\t\tswitch stmt.ReflectValue.Kind() {\n\t\tcase reflect.Slice, reflect.Array:\n\t\t\trValLen := stmt.ReflectValue.Len()\n\t\t\tif rValLen == 0 {\n\t\t\t\tstmt.AddError(gorm.ErrEmptySlice)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tstmt.SQL.Grow(rValLen * 18)\n\t\t\tstmt.Vars = make([]interface{}, 0, rValLen*len(values.Columns))\n\t\t\tvalues.Values = make([][]interface{}, rValLen)\n\n\t\t\tdefaultValueFieldsHavingValue := map[*schema.Field][]interface{}{}\n\t\t\tfor i := 0; i < rValLen; i++ {\n\t\t\t\trv := reflect.Indirect(stmt.ReflectValue.Index(i))\n\t\t\t\tif !rv.IsValid() {\n\t\t\t\t\tstmt.AddError(fmt.Errorf(\"slice data #%v is invalid: %w\", i, gorm.ErrInvalidData))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tvalues.Values[i] = make([]interface{}, len(values.Columns))\n\t\t\t\tfor idx, column := range values.Columns {\n\t\t\t\t\tfield := stmt.Schema.FieldsByDBName[column.Name]\n\t\t\t\t\tif values.Values[i][idx], isZero = field.ValueOf(stmt.Context, rv); isZero {\n\t\t\t\t\t\tif field.DefaultValueInterface != nil {\n\t\t\t\t\t\t\tvalues.Values[i][idx] = field.DefaultValueInterface\n\t\t\t\t\t\t\tstmt.AddError(field.Set(stmt.Context, rv, field.DefaultValueInterface))\n\t\t\t\t\t\t} else if field.AutoCreateTime > 0 || field.AutoUpdateTime > 0 {\n\t\t\t\t\t\t\tstmt.AddError(field.Set(stmt.Context, rv, curTime))\n\t\t\t\t\t\t\tvalues.Values[i][idx], _ = field.ValueOf(stmt.Context, rv)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if field.AutoUpdateTime > 0 && updateTrackTime {\n\t\t\t\t\t\tstmt.AddError(field.Set(stmt.Context, rv, curTime))\n\t\t\t\t\t\tvalues.Values[i][idx], _ = field.ValueOf(stmt.Context, rv)\n\t\t\t\t\t}","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/go-gorm/gorm/blob/1d6ce99528060be18a42be09aca8d39efcb47f28/callbacks/create.go#L273-L309","documentation":"In the create callback for slice destinations, each element is retrieved with reflect.Indirect(stmt.ReflectValue.Index(i)); if the resulting value is not valid (rv.IsValid() == false), GORM adds fmt.Errorf(\"slice data #%v is invalid: %w\", i, gorm.ErrInvalidData) and aborts. An invalid reflect value here means the slice slot holds something unrepresentable - classically a nil element in a slice of non-pointer structs, or a nil interface element.","triggerScenarios":"db.Create(&users) where users is []User and one element is the zero struct is fine - the real trigger is []interface{} or []*User containing nil, or a slice of a type whose element cannot be indirected to a valid value (e.g. nil map/chan-typed elements).","commonSituations":"Building []interface{} from mixed sources (JSON decode, goroutine fan-in) and inserting without filtering nils; []*User with a nil appended as a placeholder; partial batch construction where an index was allocated but never filled.","solutions":["Filter nil/invalid elements out of the slice before Create.","Prefer []*User (Create skips nil pointers for typed slices is NOT true - filter anyway) and construct slices with exact length via make([]*User, 0, n) + append.","Validate each element with reflect or a plain nil check in batch-building code.","If holes are expected, use CreateInBatches on cleaned sub-slices."],"exampleFix":"// before\nusers := []*User{u1, nil, u3}\ndb.Create(&users) // slice data #1 is invalid\n\n// after\nclean := users[:0]\nfor _, u := range users {\n    if u != nil { clean = append(clean, u) }\n}\ndb.Create(&clean)","handlingStrategy":"validation","validationCode":"func dropInvalid[T any](in []*T) []*T {\n    out := make([]*T, 0, len(in))\n    for _, v := range in {\n        if v != nil { out = append(out, v) }\n    }\n    return out\n}\n// before create:\ndb.Create(&dropInvalid(users))","typeGuard":"func allValid[T any](in []*T) bool {\n    for _, v := range in { if v == nil { return false } }\n    return true\n}","tryCatchPattern":"if err := db.Create(&users).Error; err != nil {\n    if errors.Is(err, gorm.ErrInvalidData) {\n        // clean the slice (remove nils) and retry once\n    }\n    return err\n}","preventionTips":["Build batches with append, never by index assignment into a pre-sized slice.","Filter nils at the boundary where external data becomes models."],"tags":["gorm","create","batch","nil","slice"],"backgroundTag":null,"analyzedSha":"1d6ce99528060be18a42be09aca8d39efcb47f28","analyzedAt":"2026-08-15T13:01:23.433Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}