go-sql-driver/mysql · error
unsupported type %T, a slice of %s
Error message
unsupported type %T, a slice of %s
What it means
The driver's converter (statement.go:206) encountered a slice whose element type is not byte/uint8 and not json.RawMessage. Only []byte and json.RawMessage slices are accepted; slices of any other element type (e.g. []int, []string) cannot be transmitted as a single parameter.
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 c426bd9379)
Solutions
- For IN clauses, build the placeholders manually and pass each element as a separate argument.
- Marshal non-byte slices to JSON and pass the resulting []byte.
- Convert the slice to a formatted string if the SQL expects that representation.
Example fix
// before — []int as a single arg
ids := []int{1, 2, 3}
db.Query("SELECT * FROM t WHERE id IN (?)", ids)
// after — expand placeholders
ph := strings.TrimSuffix(strings.Repeat("?,", len(ids)), ",")
args := make([]any, len(ids))
for i, id := range ids { args[i] = id }
db.Query("SELECT * FROM t WHERE id IN ("+ph+")", args...) Defensive patterns
Strategy: type-guard
Validate before calling
func isBindableSlice(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(nil))
} Type guard
func acceptableArg(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(nil))
} Try / catch
if _, err := db.Query(q, arg); err != nil {
if strings.Contains(err.Error(), "a slice of") {
// expand IN-clause placeholders or marshal the slice to []byte
}
} Prevention
- Never pass non-byte slices as parameters.
- Build IN-clause placeholders explicitly rather than relying on the driver.
- Marshal collections to JSON []byte when a single value is needed.
When it happens
Trigger: Passing []int{1,2,3}, []string{"a","b"}, or any non-byte slice directly as a query/exec argument, often expecting IN-clause expansion or automatic serialization.
Common situations: Expecting the driver to expand a slice into an IN (...) clause (it does not); passing a collection expecting automatic JSON encoding; passing a typed slice from a domain model.
Related errors
- non-Value type %T returned from Value
- 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/b82f27529b3be982.json.
Report an issue: GitHub.