go-sql-driver/mysql · error
non-Value type %T returned from Value
Error message
non-Value type %T returned from Value
What it means
In the driver's converter (statement.go:180), a type implementing driver.Valuer returned a value from its Value() method that is not a valid driver.Value (nil, int64, float64, bool, []byte, string, time.Time) nor uint64 (a driver-specific allowance). The contract of driver.Valuer.Value() is to return one of those base types; returning anything else is a bug in the Valuer implementation.
Source
Thrown at statement.go:180
if driver.IsValue(v) {
return v, nil
}
if vr, ok := v.(driver.Valuer); ok {
sv, err := callValuerValue(vr)
if err != nil {
return nil, err
}
if driver.IsValue(sv) {
return sv, nil
}
// A value returned from the Valuer interface can be "a type handled by
// a database driver's NamedValueChecker interface" so we should accept
// uint64 here as well.
if u, ok := sv.(uint64); ok {
return u, nil
}
return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
} else {
return c.ConvertValue(rv.Elem().Interface())
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return rv.Uint(), nil
case reflect.Float32, reflect.Float64:
return rv.Float(), nil
case reflect.Bool:
return rv.Bool(), nilView on GitHub (pinned to c426bd9379)
Solutions
- Make Value() return one of the allowed base types, most commonly int64, float64, string, []byte, or time.Time.
- Convert numeric custom types explicitly, e.g. return int64(m), nil.
- Return nil, nil to represent SQL NULL.
Example fix
// before
func (m Money) Value() (driver.Value, error) { return int(m), nil }
// after
func (m Money) Value() (driver.Value, error) { return int64(m), nil } Defensive patterns
Strategy: type-guard
Validate before calling
func checkValuer(v driver.Valuer) error {
val, err := v.Value()
if err != nil { return err }
switch val.(type) {
case nil, int64, uint64, float64, bool, []byte, string, time.Time:
return nil
}
return fmt.Errorf("Value() returned unsupported type %T", val)
} Type guard
func isDriverValue(v any) bool {
switch v.(type) {
case nil, int64, uint64, float64, bool, []byte, string, time.Time:
return true
}
return false
} Try / catch
if _, err := stmt.Exec(ctx, customVal); err != nil {
if strings.Contains(err.Error(), "non-Value type") {
// fix the custom type's Value() to return a base driver.Value
}
} Prevention
- Always return a base driver.Value from Value().
- Convert numeric custom types to int64/uint64 explicitly.
- Unit-test Valuer implementations against the driver.
When it happens
Trigger: A custom type's Value() returns a plain int (not int64), a float32, a struct, a *big.Int, or any non-base wrapper type; a Valuer that returns another custom type instead of unwrapping it.
Common situations: Implementing Value() to return int/uint/float32 directly; returning a nested wrapper type; misunderstanding the driver.Value type set.
Related errors
- unsupported type %T, a slice of %s
- unsupported type %T, a %s
- cannot convert type: %T
- mysql: driver does not support the use of Named Parameters
- mysql: unsupported isolation level: %v
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/64cbfbab1d8030f0.json.
Report an issue: GitHub.