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

  1. Use a unique vindex (hash, consistent_lookup_unique) as the sharding vindex for streamed tables.
  2. Fix the lookup vindex table contents so the key maps to exactly one destination.
  3. 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

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


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