go-sql-driver/mysql · error
unsupported type %T, a slice of
Error message
unsupported type %T, a slice of %s
What it means
ConvertValue only accepts byte slices ([]byte) and json.RawMessage among slice types; a slice of any other element kind is unsupported and rejected, naming the element Kind in the message.
Solutions
- Serialize the slice yourself (e.g. JSON-encode to []byte/string) before passing it.
- Expand the slice into one '?' placeholder per element and pass each element separately.
- Store the collection as JSON/TEXT in a single column.
Example fix
// before
stmt.Exec([]string{"a","b"}) // SQL: INSERT INTO t(tags) VALUES (?)
// after (JSON-encode)
b, _ := json.Marshal([]string{"a","b"})
stmt.Exec(string(b)) Defensive patterns
Strategy: validation
Validate before calling
// Reject non-byte slices before Exec.
func okArg(v any) bool {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Slice && rv.Type().Elem().Kind() != reflect.Uint8 {
return false
}
return true
} Type guard
func isSupportedSlice(v any) bool {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Slice { return true }
return rv.Type().Elem().Kind() == reflect.Uint8 || rv.Type() == reflect.TypeOf(json.RawMessage{})
} Try / catch
// Returned from Exec/Query for unsupported slice arguments.
if _, err := stmt.Exec(args...); err != nil {
if strings.Contains(err.Error(), "a slice of") {
// JSON-encode or expand the slice
}
} Prevention
- Don't pass non-byte slices to prepared statements; serialize first.
- Expand arrays into multiple placeholders when feasible.
- Add a pre-Exec guard rejecting unsupported slice kinds.
When it happens
Trigger: Passing []int, []string, []MyType, or any non-byte slice as a prepared-statement argument.
Common situations: Expecting the driver to expand/serialize arrays automatically; passing a slice where a single value was intended.
Related errors
- cannot convert type: %T
- non-Value type %T returned from Value
- unsupported type %T, a
- argument count mismatch
- can't convert %T to time.Time
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/b82f27529b3be982.
Report an issue: GitHub.
Appendix: source
Thrown at statement.go:206
} 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(), nil
case reflect.Slice:
switch t := rv.Type(); {
case t == jsonType:
return v, nil
case t.Elem().Kind() == reflect.Uint8:
return rv.Bytes(), nil
default:
return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, t.Elem().Kind())
}
case reflect.String:
return rv.String(), nil
}
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}
var valuerReflectType = reflect.TypeFor[driver.Valuer]()
// callValuerValue returns vr.Value(), with one exception:
// If vr.Value is an auto-generated method on a pointer type and the
// pointer is nil, it would panic at runtime in the panicwrap
// method. Treat it like nil instead.
//
// This is so people can implement driver.Value on value types and
// still use nil pointers to those types to mean nil/NULL, just like
// string/*string.
//View on GitHub (pinned to 03d76c7e07)