vitessio/vitess · error
type %T not supported as bind var: %v
Error message
type %T not supported as bind var: %v
What it means
Returned by bind variable conversion code when a value of an unsupported Go type is passed as a bind variable; only the types known to sqltypes (integers, strings, []byte, bool, float, sqltypes.Value, query.BindVariable, etc.) are accepted.
Source
Thrown at go/sqltypes/bind_variables.go:331
return bv, nil
case []Value:
bv := &querypb.BindVariable{
Type: querypb.Type_TUPLE,
Values: make([]*querypb.Value, len(v)),
}
values := make([]querypb.Value, len(v))
for i, lv := range v {
lbv, err := BuildBindVariable(lv)
if err != nil {
return nil, err
}
values[i].Type = lbv.Type
values[i].Value = lbv.Value
bv.Values[i] = &values[i]
}
return bv, nil
}
return nil, fmt.Errorf("type %T not supported as bind var: %v", v, v)
}
// ValidateBindVariables validates a map[string]*querypb.BindVariable.
func ValidateBindVariables(bv map[string]*querypb.BindVariable) error {
for k, v := range bv {
if err := ValidateBindVariable(v); err != nil {
return fmt.Errorf("%s: %v", k, err)
}
}
return nil
}
// ValidateBindVariable returns an error if the bind variable has inconsistent
// fields.
func ValidateBindVariable(bv *querypb.BindVariable) error {
if bv == nil {
return errors.New("bind variable is nil")
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Convert the value to a supported type before binding: string, int/uint/float variants, []byte, time.Time, or []T of a supported scalar
- For nil, use a typed value such as sqltypes.NULL via an explicit conversion
- For lists, build a []string or []int64 etc. of a supported element type
- Inspect %T in the message to identify exactly which type leaked in
Example fix
// before
bindVars["filter"] = struct{ A int }{A: 1}
// after
bindVars["filter"] = 1 // or serialize to []byte / JSON string if intended Defensive patterns
Strategy: type-guard
Validate before calling
if !isBindable(v) { return fmt.Errorf("cannot bind %T", v) } Type guard
func isBindable(v interface{}) bool {
switch v.(type) {
case nil, string, []byte, int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, float32, float64,
time.Time, *querypb.BindVariable:
return true
}
return false
} Try / catch
bv, err := sqltypes.BuildBindVariable(v)
if err != nil {
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "bind var %v: %v", v, err)
} Prevention
- Convert custom types at the boundary to scalars/[]byte before binding
- Use explicit serialization (JSON/protobuf bytes) for complex values
- Avoid interface{} plumbing that lets arbitrary types reach bind calls
When it happens
Trigger: Passing an unsupported Go type (struct, map, channel, func, nil without a type, nested unsupported slice elements) to BuildBindVariable, directly or via BuildBindVariables.
Common situations: Passing protobuf messages or structs instead of scalars; passing typed-nil pointers; passing slices of unsupported element types; values produced by generic deserialization (JSON/YAML) that need conversion.
Related errors
- %s: %v
- --batch-size only allowed when all queries are CREATE TABLE|
- UnescapeID err: invalid input identifier '%s'
- UnescapeID err: unexpected single backtick at position %d in
- UnescapeID err: no outer backticks found in the identifier '
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/e0c1d9dd0aa0e431.
Report an issue: GitHub.