vitessio/vitess · error
panic(err)
Error message
panic(err)
What it means
`evalTuple.ToRawBytes()` serializes a tuple of inner values back into a proto-encoded tuple. Each inner value is re-wrapped with `sqltypes.NewValue(type, bytes)`; if that validation fails (type/bytes mismatch for an element), the code panics with the underlying error. This indicates an internal inconsistency — an element in the evalTuple cannot be represented as a valid sqltypes.Value.
Source
Thrown at go/vt/vtgate/evalengine/eval_tuple.go:52
for _, value := range values {
val := sqltypes.ProtoToValue(value)
e, err := valueToEval(val, typedCoercionCollation(val.Type(), collations.CollationForType(val.Type(), collation)), nil)
if err != nil {
return nil, err
}
evals = append(evals, e)
}
return &evalTuple{t: evals}, nil
}
func (e *evalTuple) ToRawBytes() []byte {
vals := make([]sqltypes.Value, 0, len(e.t))
for _, e2 := range e.t {
v, err := sqltypes.NewValue(e2.SQLType(), e2.ToRawBytes())
if err != nil {
panic(err)
}
vals = append(vals, v)
}
return sqltypes.TupleToProto(vals).Value
}
func (e *evalTuple) SQLType() sqltypes.Type {
return sqltypes.Tuple
}
func (e *evalTuple) Size() int32 {
return 0
}
func (e *evalTuple) Scale() int32 {
return 0
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect the tuple element that fails NewValue and fix how its type/bytes are produced
- Validate inner values when building evalTuple rather than at serialization time
- Replace the raw panic with a wrapped error at the public API boundary
- Report as a Vitess bug if reproducible on a released version
Example fix
// before
if err != nil {
panic(err)
}
// after
if err != nil {
panic(vterrors.Wrapf(err, "cannot serialize tuple element of type %v", e2.SQLType())) Defensive patterns
Strategy: type-guard
Validate before calling
for _, e2 := range e.t {
if _, err := sqltypes.NewValue(e2.SQLType(), e2.ToRawBytes()); err != nil {
return vterrors.Wrapf(err, "invalid tuple element type %v", e2.SQLType())
}
} Type guard
func isValidTupleElement(v evalengine.Eval) bool {
_, err := sqltypes.NewValue(v.SQLType(), v.ToRawBytes())
return err == nil
} Try / catch
func safeToRawBytes(e *evalengine.EvalTuple) (b []byte, err error) {
defer func() {
if r := recover(); r != nil {
err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "tuple serialization panic: %v", r)
}
}()
return e.ToRawBytes(), nil
} Prevention
- Validate element types when constructing evalTuple, not at serialization
- Only place engine-produced eval values into tuples
- Add a unit test serializing tuples of every supported eval type
When it happens
Trigger: Calling ToRawBytes() on an evalTuple containing an element whose SQLType/bytes combination is rejected by sqltypes.NewValue (e.g. an invalid or unsupported type produced by the engine).
Common situations: Hit during Vitess development when new eval types are added to tuples without ensuring NewValue accepts their serialized form; not reachable from normal SQL execution.
Related errors
- Value.ForEachValue on non-tuple
- malformed hex literal from parser
- bad unsigned integer type
- bad type aggregation for signed/unsigned types
- unreachable
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/80f4af6976943a6b.
Report an issue: GitHub.