vitessio/vitess · error
Numeric.ReverseMap: length of keyspaceId is not 8: %d
Error message
Numeric.ReverseMap: length of keyspaceId is not 8: %d
What it means
Numeric.ReverseMap expects every keyspace id to be exactly 8 bytes (a big-endian uint64). Any shorter/longer id means the keyspace id was not produced by the Numeric vindex, so it cannot be reversed to its numeric id. This usually signals the wrong vindex type is associated with the table or corrupted mapping data.
Source
Thrown at go/vt/vtgate/vindexes/numeric.go:104
func (vind *Numeric) Map(ctx context.Context, vcursor VCursor, ids []sqltypes.Value) ([]key.ShardDestination, error) {
out := make([]key.ShardDestination, 0, len(ids))
for _, id := range ids {
ksid, err := vind.Hash(id)
if err != nil {
out = append(out, key.DestinationNone{})
continue
}
out = append(out, key.DestinationKeyspaceID(ksid))
}
return out, nil
}
// ReverseMap returns the associated ids for the ksids.
func (*Numeric) ReverseMap(_ VCursor, ksids [][]byte) ([]sqltypes.Value, error) {
reverseIds := make([]sqltypes.Value, len(ksids))
for i, keyspaceID := range ksids {
if len(keyspaceID) != 8 {
return nil, fmt.Errorf("Numeric.ReverseMap: length of keyspaceId is not 8: %d", len(keyspaceID))
}
val := binary.BigEndian.Uint64(keyspaceID)
reverseIds[i] = sqltypes.NewUint64(val)
}
return reverseIds, nil
}
// RangeMap implements Between.
func (vind *Numeric) RangeMap(ctx context.Context, vcursor VCursor, startId sqltypes.Value, endId sqltypes.Value) ([]key.ShardDestination, error) {
startKsId, err := vind.Hash(startId)
if err != nil {
return nil, err
}
endKsId, err := vind.Hash(endId)
if err != nil {
return nil, err
}
out := []key.ShardDestination{&key.DestinationKeyRange{KeyRange: key.NewKeyRange(startKsId, endKsId)}}View on GitHub (pinned to 01a25a7d17)
Solutions
- Confirm the vindex type in the vschema matches the one that generated the keyspace ids (numeric -> 8 bytes).
- If the table used a different vindex (e.g. binary_md5, 16 bytes), use that vindex type for reversal.
- Rebuild the mapping/lookup data with the correct vindex before running reverse workflows.
Example fix
// before (vschema)
"vindex": {"type": "numeric"} // but keys are 16-byte md5
// after
"vindex": {"type": "binary_md5"} Defensive patterns
Strategy: validation
Validate before calling
for _, ksid := range ksids {
if len(ksid) != 8 {
return errors.New("keyspace ids are not from a Numeric vindex")
}
} Type guard
func isNumericKeyspaceID(k []byte) bool { return len(k) == 8 } Prevention
- Use the same vindex type for a table across its entire lifecycle.
- Check keyspace-id length (8 for numeric) when migrating vindex types.
- Rebuild reverse lookup data with the correct vindex before reversal workflows.
When it happens
Trigger: Calling ReverseMap on a Numeric vindex with a keyspace id whose length != 8, e.g. during vindex reversal workflows (MoveTables/Reshard reverse lookup) when the mapping table contains ids generated by a different vindex (Binary, Hash produce 8 bytes too, but BinaryMD5 produces 16).
Common situations: Table was migrated from another vindex type (e.g. binary_md5) but the vschema now claims numeric; lookup/reverse workflow fed with mixed-length keyspace ids; manually crafted keyspace ids in test code.
Related errors
- invalid keyspace id: %v
- mapping row to keyspace id returned an invalid array of dest
- could not map %v to a keyspace id, got destination %v
- one or two tables must be specified
- at least one table must be specified
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/49395f77520b0b59.
Report an issue: GitHub.