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

  1. Inspect the tuple element that fails NewValue and fix how its type/bytes are produced
  2. Validate inner values when building evalTuple rather than at serialization time
  3. Replace the raw panic with a wrapped error at the public API boundary
  4. 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

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


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