{"record":{"id":"b2cdf467cc6b09fb","repo":"ent/ent","slug":"gotype-q-for-field-q-must-be-converted-to-the-ba","errorCode":null,"errorMessage":"GoType %q for field %q must be converted to the basic %q type for validators","messagePattern":"GoType %q for field %q must be converted to the basic %q type for validators","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"entc/gen/type.go","lineNumber":1039,"sourceCode":"func (t *Type) checkField(tf *Field, f *load.Field) (err error) {\n\tswitch ant := tf.EntSQL(); {\n\tcase f.Name == \"\":\n\t\terr = fmt.Errorf(\"field name cannot be empty\")\n\tcase f.Info == nil || !f.Info.Valid():\n\t\terr = fmt.Errorf(\"invalid type for field %s\", f.Name)\n\tcase f.Unique && f.Default && f.DefaultKind != reflect.Func:\n\t\terr = fmt.Errorf(\"unique field %q cannot have default value\", f.Name)\n\tcase t.fields[f.Name] != nil:\n\t\terr = fmt.Errorf(\"field %q redeclared for type %q\", f.Name, t.Name)\n\tcase f.Sensitive && f.Tag != \"\":\n\t\terr = fmt.Errorf(\"sensitive field %q cannot have struct tags\", f.Name)\n\tcase f.Info.Type == field.TypeEnum:\n\t\tif tf.Enums, err = tf.enums(f); err == nil && !tf.HasGoType() {\n\t\t\t// Enum types should be named as follows: typepkg.Field.\n\t\t\tf.Info.Ident = fmt.Sprintf(\"%s.%s\", t.PackageDir(), pascal(f.Name))\n\t\t}\n\tcase tf.Validators > 0 && !tf.ConvertedToBasic() && f.Info.Type != field.TypeJSON:\n\t\terr = fmt.Errorf(\"GoType %q for field %q must be converted to the basic %q type for validators\", tf.Type, f.Name, tf.Type.Type)\n\tcase ant != nil && ant.Default != \"\" && (ant.DefaultExpr != \"\" || ant.DefaultExprs != nil):\n\t\terr = fmt.Errorf(\"field %q cannot have both default value and default expression annotations\", f.Name)\n\tcase tf.HasValueScanner() && tf.IsJSON():\n\t\terr = fmt.Errorf(\"json field %q cannot have an external ValueScanner\", f.Name)\n\t}\n\treturn err\n}\n\n// UnexportedForeignKeys returns all foreign-keys that belong to the type\n// but are not exported (not defined with field). i.e. generated by ent.\nfunc (t Type) UnexportedForeignKeys() []*ForeignKey {\n\tfks := make([]*ForeignKey, 0, len(t.ForeignKeys))\n\tfor _, fk := range t.ForeignKeys {\n\t\tif !fk.UserDefined {\n\t\t\tfks = append(fks, fk)\n\t\t}\n\t}\n\treturn fks","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/ent/ent/blob/69d5d4deb19599f129166634e09d33addcf3f2cc/entc/gen/type.go#L1021-L1057","documentation":"A field declares Validators > 0, uses a custom GoType that is not convertible to its underlying basic ent type, and is not a JSON field. ent's validators run on the basic type, so an unconverted custom type cannot be validated; codegen aborts.","triggerScenarios":"Schema definition like `field.Other(\"x\", CustomType{}).Validators(1)` where CustomType does not implement conversion to the basic type (no GoType with basic underlying / ConvertedToBasic() false), then running `ent generate`.","commonSituations":"Wrapping primitives in domain types (e.g. type Email string) without declaring the basic type mapping via field.String(...).GoType(Email{}) style APIs; adding validators after introducing a GoType.","solutions":["Use the typed constructor with GoType so ent knows the basic type: e.g. field.String(\"x\").GoType(MyString(\"\")).Validators(1).","Ensure the custom type's underlying type matches the basic ent type so ConvertedToBasic() returns true.","Move validation into the custom type or application layer and drop .Validators(...) if conversion isn't possible."],"exampleFix":"// before\nfield.Other(\"email\", Email(\"\")).Validators(1)\n\n// after\nfield.String(\"email\").GoType(Email(\"\")).Validators(1)","handlingStrategy":"validation","validationCode":"d := f.Descriptor()\nif d.Validators > 0 && usesCustomGoType(d) && !convertsToBasic(d) && d.Info.Type != field.TypeJSON {\n    return fmt.Errorf(\"field %s: GoType must convert to basic type for validators\", d.Name)\n}","typeGuard":"func validatorsRequireBasic(d *field.TypeInfo, validators int) bool {\n    return validators > 0 && d.Type != field.TypeJSON\n}","tryCatchPattern":null,"preventionTips":["Prefer field.String(...).GoType(CustomString{}) over field.Other for custom types needing validators.","Keep custom types with underlying basic types so conversion works.","Move complex validation into the type itself when conversion isn't possible."],"tags":["codegen","schema","validators","custom-types"],"backgroundTag":"schema-field-validation","analyzedSha":"69d5d4deb19599f129166634e09d33addcf3f2cc","analyzedAt":"2026-09-03T16:51:39.799Z","contentChangedAt":"2026-09-03T16:51:39.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}