vitessio/vitess · error

UnicodeLooseXXHash.Map: %v

Error message

UnicodeLooseXXHash.Map: %v

What it means

UnicodeLooseXXHash.Map hashes ids (unicode collation + xxhash) to pick shard destinations and wraps any Hash failure in 'UnicodeLooseXXHash.Map: %v'. The only causes are values that cannot be converted to bytes or invalid UTF-8 content. The query fails before any shard routing happens.

Source

Thrown at go/vt/vtgate/vindexes/unicodeloosexxhash.go:91

func (vind *UnicodeLooseXXHash) Verify(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) {
	out := make([]bool, 0, len(ids))
	for i, id := range ids {
		data, err := vind.Hash(id)
		if err != nil {
			return nil, fmt.Errorf("UnicodeLooseXXHash.Verify: %v", err)
		}
		out = append(out, bytes.Equal(data, ksids[i]))
	}
	return out, nil
}

// Map can map ids to key.ShardDestination objects.
func (vind *UnicodeLooseXXHash) Map(ctx context.Context, vcursor VCursor, ids []sqltypes.Value) ([]key.ShardDestination, error) {
	out := make([]key.ShardDestination, 0, len(ids))
	for _, id := range ids {
		data, err := vind.Hash(id)
		if err != nil {
			return nil, fmt.Errorf("UnicodeLooseXXHash.Map: %v", err)
		}
		out = append(out, key.DestinationKeyspaceID(data))
	}
	return out, nil
}

func (vind *UnicodeLooseXXHash) Hash(id sqltypes.Value) ([]byte, error) {
	return unicodeHash(&collateXX, id)
}

// UnknownParams implements the ParamValidating interface.
func (vind *UnicodeLooseXXHash) UnknownParams() []string {
	return vind.unknownParams
}

func init() {
	Register("unicode_loose_xxhash", newUnicodeLooseXXHash)
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Identify and fix the offending value's encoding.
  2. Use utf8mb4 for the column and client connections.
  3. Migrate to a binary vindex if values are not text.
  4. Clean/re-encode corrupted rows written directly to MySQL.

Example fix

// before
client charset: latin1 → 'café' arrives as invalid bytes
// after
SET NAMES utf8mb4; before issuing queries against the unicode_loose_xxhash vindex
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight in app or test:
for _, id := range ids {
    if !utf8.ValidString(id) {
        return fmt.Errorf("non-UTF-8 id %q cannot be routed by unicode_loose_xxhash", id)
    }
}

Try / catch

dests, err := vindex.Map(ctx, vc, ids)
if err != nil {
    if strings.Contains(err.Error(), "invalid UTF-8") {
        // fix encoding then retry
    }
    return err
}

Prevention

When it happens

Trigger: A Map call (i.e. routing any query using the vindex column) receiving a non-UTF-8 or non-bytes-convertible sqltypes.Value for the vindexed column.

Common situations: Wrong connection charset (latin1/binary); storing corrupted bytes in the vindex column; programmatic callers passing tuple values.

Related errors


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