vitessio/vitess · error

%s: %v

Error message

%s: %v

What it means

BuildBindVariables converts a map of Go values into query bind variables. It wraps any per-key failure from BuildBindVariable with the offending key name, so this '%s: %v' error carries the unsupported key plus the underlying cause.

Source

Thrown at go/sqltypes/bind_variables.go:71

	return &querypb.Value{Type: v.Type(), Value: v.val}
}

// ProtoToValue converts a *querypb.Value to a Value.
func ProtoToValue(v *querypb.Value) Value {
	return MakeTrusted(v.Type, v.Value)
}

// BuildBindVariables builds a map[string]*querypb.BindVariable from a map[string]any
func BuildBindVariables(in map[string]any) (map[string]*querypb.BindVariable, error) {
	if len(in) == 0 {
		return nil, nil
	}

	out := make(map[string]*querypb.BindVariable, len(in))
	for k, v := range in {
		bv, err := BuildBindVariable(v)
		if err != nil {
			return nil, fmt.Errorf("%s: %v", k, err)
		}
		out[k] = bv
	}
	return out, nil
}

// HexNumBindVariable converts bytes representing a hex number to a bind var.
func HexNumBindVariable(v []byte) *querypb.BindVariable {
	return ValueBindVariable(NewHexNum(v))
}

// HexValBindVariable converts bytes representing a hex encoded string to a bind var.
func HexValBindVariable(v []byte) *querypb.BindVariable {
	return ValueBindVariable(NewHexVal(v))
}

// BitNumBindVariable converts bytes representing a bit encoded string to a bind var.
func BitNumBindVariable(v []byte) *querypb.BindVariable {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Read the wrapped key and underlying message to find the offending bind variable
  2. Convert the value to a supported type (scalar, []byte, time.Time, or a typed list) before calling
  3. Pre-validate values with BuildBindVariable individually in a loop to isolate the bad key

Example fix

// before
vars := map[string]interface{}{"user": user} // user is a struct
// after
vars := map[string]interface{}{"user": user.ID} // pass a supported scalar
Defensive patterns

Strategy: validation

Validate before calling

func validateBindValues(in map[string]interface{}) error {
	for k, v := range in {
		if _, err := sqltypes.BuildBindVariable(v); err != nil {
			return fmt.Errorf("key %q: %v", k, err)
		}
	}
	return nil
}

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

vars, err := sqltypes.BuildBindVariables(in)
if err != nil {
	return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "bad bind vars: %v", err)
}

Prevention

When it happens

Trigger: Calling BuildBindVariables (used by ExecOnTablet / ExecOnVTGate) with a map containing a value whose type BuildBindVariable cannot encode (unsupported type, nil, bad slice, etc.).

Common situations: Passing custom structs, maps, or nil pointers as bind values; a refactor changed a value's type; JSON-decoded data produced interface{} values of unexpected types.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/5c62c1c088a1fa50. Report an issue: GitHub.