{"record":{"id":"62b243d85f9eea89","repo":"vitessio/vitess","slug":"unicodeloosexxhash-map-v","errorCode":null,"errorMessage":"UnicodeLooseXXHash.Map: %v","messagePattern":"UnicodeLooseXXHash\\.Map: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/vindexes/unicodeloosexxhash.go","lineNumber":91,"sourceCode":"func (vind *UnicodeLooseXXHash) Verify(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) {\n\tout := make([]bool, 0, len(ids))\n\tfor i, id := range ids {\n\t\tdata, err := vind.Hash(id)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"UnicodeLooseXXHash.Verify: %v\", err)\n\t\t}\n\t\tout = append(out, bytes.Equal(data, ksids[i]))\n\t}\n\treturn out, nil\n}\n\n// Map can map ids to key.ShardDestination objects.\nfunc (vind *UnicodeLooseXXHash) Map(ctx context.Context, vcursor VCursor, ids []sqltypes.Value) ([]key.ShardDestination, error) {\n\tout := make([]key.ShardDestination, 0, len(ids))\n\tfor _, id := range ids {\n\t\tdata, err := vind.Hash(id)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"UnicodeLooseXXHash.Map: %v\", err)\n\t\t}\n\t\tout = append(out, key.DestinationKeyspaceID(data))\n\t}\n\treturn out, nil\n}\n\nfunc (vind *UnicodeLooseXXHash) Hash(id sqltypes.Value) ([]byte, error) {\n\treturn unicodeHash(&collateXX, id)\n}\n\n// UnknownParams implements the ParamValidating interface.\nfunc (vind *UnicodeLooseXXHash) UnknownParams() []string {\n\treturn vind.unknownParams\n}\n\nfunc init() {\n\tRegister(\"unicode_loose_xxhash\", newUnicodeLooseXXHash)\n}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/vindexes/unicodeloosexxhash.go#L73-L109","documentation":"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.","triggerScenarios":"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.","commonSituations":"Wrong connection charset (latin1/binary); storing corrupted bytes in the vindex column; programmatic callers passing tuple values.","solutions":["Identify and fix the offending value's encoding.","Use utf8mb4 for the column and client connections.","Migrate to a binary vindex if values are not text.","Clean/re-encode corrupted rows written directly to MySQL."],"exampleFix":"// before\nclient charset: latin1 → 'café' arrives as invalid bytes\n// after\nSET NAMES utf8mb4; before issuing queries against the unicode_loose_xxhash vindex","handlingStrategy":"validation","validationCode":"// pre-flight in app or test:\nfor _, id := range ids {\n    if !utf8.ValidString(id) {\n        return fmt.Errorf(\"non-UTF-8 id %q cannot be routed by unicode_loose_xxhash\", id)\n    }\n}","typeGuard":null,"tryCatchPattern":"dests, err := vindex.Map(ctx, vc, ids)\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid UTF-8\") {\n        // fix encoding then retry\n    }\n    return err\n}","preventionTips":["Set connection charset to utf8mb4","Sanitize inputs at the API boundary","Avoid storing binary payloads in vindexed text columns","Monitor for charset-mismatch warnings in app drivers"],"tags":["vtgate","vindex","utf-8","xxhash","routing"],"backgroundTag":"invalid-utf8-vindex-value","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}