go-gorm/gorm · error

invalid field type %#v for UnixSecondSerializer, only int, u

Error message

invalid field type %#v for UnixSecondSerializer, only int, uint supported

What it means

UnixSecondSerializer.Value only accepts signed/unsigned integers and their pointer forms. Any other Go type on a field tagged with serializer:unixsecond — time.Time, string, float, bool, structs — hits the default branch and is rejected with the field's actual type printed via %#v.

Source

Thrown at schema/serializer.go:155

		} else {
			result = time.Unix(int64(uv), 0).UTC() //nolint:gosec
		}
	case *int, *int8, *int16, *int32, *int64:
		if rv.IsZero() {
			return nil, nil
		}
		result = time.Unix(rv.Elem().Int(), 0).UTC()
	case *uint, *uint8, *uint16, *uint32, *uint64:
		if rv.IsZero() {
			return nil, nil
		}
		if uv := rv.Elem().Uint(); uv > math.MaxInt64 {
			err = fmt.Errorf("integer overflow conversion uint64(%d) -> int64", uv)
		} else {
			result = time.Unix(int64(uv), 0).UTC() //nolint:gosec
		}
	default:
		err = fmt.Errorf("invalid field type %#v for UnixSecondSerializer, only int, uint supported", fieldValue)
	}
	return
}

// GobSerializer gob serializer
type GobSerializer struct{}

// Scan implements serializer interface
func (GobSerializer) Scan(ctx context.Context, field *Field, dst reflect.Value, dbValue interface{}) (err error) {
	fieldValue := reflect.New(field.FieldType)

	if dbValue != nil {
		var bytesValue []byte
		switch v := dbValue.(type) {
		case []byte:
			bytesValue = v
		default:
			return fmt.Errorf("failed to unmarshal gob value: %#v", dbValue)

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Remove the serializer tag from time.Time fields — GORM stores them natively.
  2. Keep the tag only on integer (or integer-pointer) fields.
  3. For string inputs, parse to int64 in a setter/BeforeSave hook rather than relying on the serializer.

Example fix

// before
CreatedAt time.Time `gorm:"serializer:unixsecond"` // unsupported type

// after
CreatedAt time.Time // native handling
Defensive patterns

Strategy: type-guard

Validate before calling

// Only integer kinds may carry the unixsecond serializer
func unixSecondTagValid(f reflect.StructField) bool {
    if !strings.Contains(f.Tag.Get("gorm"), "unixsecond") { return true }
    switch f.Type.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
         reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Ptr:
        return true
    }
    return false
}

Type guard

func isUnixSecondCompatible(v any) bool {
    switch v.(type) {
    case int, int8, int16, int32, int64,
         uint, uint8, uint16, uint32, uint64,
         *int, *int8, *int16, *int32, *int64,
         *uint, *uint8, *uint16, *uint32, *uint64:
        return true
    }
    return false
}

Try / catch

if err := db.Create(&rec).Error; err != nil {
    if strings.Contains(err.Error(), "UnixSecondSerializer") {
        return fmt.Errorf("field type incompatible with unixsecond serializer; use int fields or drop the tag: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Changing a field from int64 to time.Time but keeping `gorm:"serializer:unixsecond"`; applying the tag to string-encoded timestamps; floats used for second fractions.

Common situations: Model evolution where the tag outlives the type; copy-pasting the serializer tag onto time.Time fields; mixing conventions across a codebase.

Related errors


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