vitessio/vitess · error
cannot map vindex to unique keyspace id: %v
Error message
cannot map vindex to unique keyspace id: %v
What it means
During DML vindex maintenance, resolveKeyspaceID expects the vindex mapping to produce a single unique DestinationKeyspaceID. If the destination is something else (a multi-keyspace-id destination, a range/scatter destination, etc.), the DML cannot identify the exact row's keyspace id and fails with this error.
Source
Thrown at go/vt/vtgate/engine/dml.go:135
var destinations []key.ShardDestination
var err error
switch vdx := vindex.(type) {
case vindexes.MultiColumn:
destinations, err = vdx.Map(ctx, vcursor, [][]sqltypes.Value{vindexKey})
case vindexes.SingleColumn:
destinations, err = vdx.Map(ctx, vcursor, vindexKey)
}
if err != nil {
return nil, err
}
switch ksid := destinations[0].(type) {
case key.DestinationKeyspaceID:
return ksid, nil
case key.DestinationNone:
return nil, nil
default:
return nil, fmt.Errorf("cannot map vindex to unique keyspace id: %v", destinations[0])
}
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure the WHERE clause uses a unique vindex (primary vindex or unique lookup vindex) so it maps to exactly one keyspace id
- Rewrite the query to include equality predicates on the primary vindex columns
- If a lookup vindex returns multiple rows, clean up duplicate entries in the lookup table
Example fix
// before UPDATE user SET name='x' WHERE email LIKE '%@a.com' // after UPDATE user SET name='x' WHERE id = 123 AND email = 'a@b.com'
Defensive patterns
Strategy: validation
Validate before calling
// ensure WHERE uses the primary/unique vindex with equality predicates
if !queryUsesUniqueVindexEquality(where) {
return errors.New("DML must filter on a unique vindex")
} Type guard
func isUniqueDestination(dest key.Destination) bool {
_, ok := dest.(key.DestinationKeyspaceID)
return ok
} Try / catch
err := executeUpdate(q)
if err != nil && strings.Contains(err.Error(), "cannot map vindex to unique keyspace id") {
// fall back to a query with an explicit unique-vindex equality predicate
} Prevention
- Always include the primary vindex columns with equality predicates in UPDATE/DELETE WHERE clauses
- Check vindex type (unique vs non-unique) before issuing DML through it
- Monitor lookup vindexes for duplicate mappings that break uniqueness
When it happens
Trigger: Executing UPDATE/DELETE whose WHERE clause resolves via a vindex to a non-unique destination (e.g. DestinationKeyRange or DestinationKeyspaceIDs) when deleteVindexEntries/updateVindexEntries call resolveKeyspaceID.
Common situations: Updating rows through a non-unique vindex or lookup vindex returning multiple keyspace ids; queries touching multiple shards through a vindex where only one unique ksid is supported.
Related errors
- Binary.ReverseMap: keyspaceId is nil
- cannot find column to use to find keyspace_id for table %v
- values %v for column %v does not map to keyspace ids
- values %v for column %v does not map to keyspace ids
- lookup.Update.convert: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/7e5263180bf9f828.
Report an issue: GitHub.