ent/ent · error

GoType %q for field %q must be converted to the basic %q typ

Error message

GoType %q for field %q must be converted to the basic %q type for validators

What it means

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.

Source

Thrown at entc/gen/type.go:1039

func (t *Type) checkField(tf *Field, f *load.Field) (err error) {
	switch ant := tf.EntSQL(); {
	case f.Name == "":
		err = fmt.Errorf("field name cannot be empty")
	case f.Info == nil || !f.Info.Valid():
		err = fmt.Errorf("invalid type for field %s", f.Name)
	case f.Unique && f.Default && f.DefaultKind != reflect.Func:
		err = fmt.Errorf("unique field %q cannot have default value", f.Name)
	case t.fields[f.Name] != nil:
		err = fmt.Errorf("field %q redeclared for type %q", f.Name, t.Name)
	case f.Sensitive && f.Tag != "":
		err = fmt.Errorf("sensitive field %q cannot have struct tags", f.Name)
	case f.Info.Type == field.TypeEnum:
		if tf.Enums, err = tf.enums(f); err == nil && !tf.HasGoType() {
			// Enum types should be named as follows: typepkg.Field.
			f.Info.Ident = fmt.Sprintf("%s.%s", t.PackageDir(), pascal(f.Name))
		}
	case tf.Validators > 0 && !tf.ConvertedToBasic() && f.Info.Type != field.TypeJSON:
		err = fmt.Errorf("GoType %q for field %q must be converted to the basic %q type for validators", tf.Type, f.Name, tf.Type.Type)
	case ant != nil && ant.Default != "" && (ant.DefaultExpr != "" || ant.DefaultExprs != nil):
		err = fmt.Errorf("field %q cannot have both default value and default expression annotations", f.Name)
	case tf.HasValueScanner() && tf.IsJSON():
		err = fmt.Errorf("json field %q cannot have an external ValueScanner", f.Name)
	}
	return err
}

// UnexportedForeignKeys returns all foreign-keys that belong to the type
// but are not exported (not defined with field). i.e. generated by ent.
func (t Type) UnexportedForeignKeys() []*ForeignKey {
	fks := make([]*ForeignKey, 0, len(t.ForeignKeys))
	for _, fk := range t.ForeignKeys {
		if !fk.UserDefined {
			fks = append(fks, fk)
		}
	}
	return fks

View on GitHub (pinned to 69d5d4deb1)

Solutions

  1. Use the typed constructor with GoType so ent knows the basic type: e.g. field.String("x").GoType(MyString("")).Validators(1).
  2. Ensure the custom type's underlying type matches the basic ent type so ConvertedToBasic() returns true.
  3. Move validation into the custom type or application layer and drop .Validators(...) if conversion isn't possible.

Example fix

// before
field.Other("email", Email("")).Validators(1)

// after
field.String("email").GoType(Email("")).Validators(1)
Defensive patterns

Strategy: validation

Validate before calling

d := f.Descriptor()
if d.Validators > 0 && usesCustomGoType(d) && !convertsToBasic(d) && d.Info.Type != field.TypeJSON {
    return fmt.Errorf("field %s: GoType must convert to basic type for validators", d.Name)
}

Type guard

func validatorsRequireBasic(d *field.TypeInfo, validators int) bool {
    return validators > 0 && d.Type != field.TypeJSON
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Related errors


AI-assisted analysis of ent/ent@69d5d4deb1 (2026-09-03). Data as JSON: /api/errors/b2cdf467cc6b09fb. Report an issue: GitHub.