vitessio/vitess · error
mapping row to keyspace id returned an invalid array of dest
Error message
mapping row to keyspace id returned an invalid array of destinations: %v
What it means
After mapping the sharding-key value through the vindex, the resolver expects exactly one destination. Any other count (zero, multiple, or scatter) is invalid for keyspace-id computation during binlog streaming.
Source
Thrown at go/vt/binlog/keyspace_id_resolver.go:110
}
}
// The column was not found.
return -1, nil, fmt.Errorf("cannot find column %v in table %v", shardingColumnName, table.Name)
}, nil
}
// keyspaceIDResolverFactoryV3 uses the Vindex to compute the value.
type keyspaceIDResolverFactoryV3 struct {
vindex vindexes.SingleColumn
}
func (r *keyspaceIDResolverFactoryV3) keyspaceID(v sqltypes.Value) ([]byte, error) {
destinations, err := r.vindex.Map(context.TODO(), nil, []sqltypes.Value{v})
if err != nil {
return nil, err
}
if len(destinations) != 1 {
return nil, fmt.Errorf("mapping row to keyspace id returned an invalid array of destinations: %v", key.DestinationsString(destinations))
}
ksid, ok := destinations[0].(key.DestinationKeyspaceID)
if !ok || len(ksid) == 0 {
return nil, fmt.Errorf("could not map %v to a keyspace id, got destination %v", v, destinations[0])
}
return ksid, nil
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Use a unique vindex (hash, consistent_lookup_unique) as the sharding vindex for streamed tables.
- Fix the lookup vindex table contents so the key maps to exactly one destination.
- Check the printed destinations string to see how many/which destinations were returned and why.
Example fix
// before (non-unique lookup vindex)
{"vindexes":{"lk":{"type":"lookup_hash_unique"...}}
// after
{"vindexes":{"lk":{"type":"consistent_lookup_unique"...}} Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the sharding vindex is unique/functional before streaming
vdef := vschema.Vindexes[vindexName]
if !isUniqueVindexType(vdef.Type) {
return fmt.Errorf("vindex %s must be unique for keyrange streaming", vindexName)
} Type guard
func isSingleKeyspaceID(dest key.Destination) bool {
_, ok := dest.(key.DestinationKeyspaceID)
return ok
} Try / catch
if err := streamKeyRange(ctx, kr); err != nil {
if strings.Contains(err.Error(), "invalid array of destinations") {
// switch to a unique vindex or repair lookup table
}
return err
} Prevention
- Use unique functional vindexes (hash, binary, unique lookup) as sharding vindexes.
- Periodically verify lookup vindex tables have exactly one row per key.
- Log destination strings when mapping anomalies appear in backups/streams.
When it happens
Trigger: keyspaceID(v) called with a vindex whose Map() returns a destinations slice with len != 1 (e.g. lookup vindex returning empty, or a vindex mapping to multiple shards).
Common situations: Using a non-unique or lookup vindex that returns no/many destinations for a row's sharding key during keyrange streaming; data inconsistency in a lookup vindex table.
Related errors
- could not map %v to a keyspace id, got destination %v
- cannot find column to use to find keyspace_id for table %v
- cannot build vschema for keyspace %v: %v
- Numeric.ReverseMap: length of keyspaceId is not 8: %d
- invalid keyspace id: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/a95011f31b0f20e5.
Report an issue: GitHub.