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

  1. Ensure the WHERE clause uses a unique vindex (primary vindex or unique lookup vindex) so it maps to exactly one keyspace id
  2. Rewrite the query to include equality predicates on the primary vindex columns
  3. 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

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


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