{"record":{"id":"ae7e3de0495750d7","repo":"vitessio/vitess","slug":"unicodeloosexxhash-verify-v","errorCode":null,"errorMessage":"UnicodeLooseXXHash.Verify: %v","messagePattern":"UnicodeLooseXXHash\\.Verify: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/vindexes/unicodeloosexxhash.go","lineNumber":78,"sourceCode":"}\n\n// IsUnique returns true since the Vindex is unique.\nfunc (vind *UnicodeLooseXXHash) IsUnique() bool {\n\treturn true\n}\n\n// NeedsVCursor satisfies the Vindex interface.\nfunc (vind *UnicodeLooseXXHash) NeedsVCursor() bool {\n\treturn false\n}\n\n// Verify returns true if ids maps to ksids.\nfunc (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}","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/vindexes/unicodeloosexxhash.go#L60-L96","documentation":"UnicodeLooseXXHash.Verify behaves like UnicodeLooseMD5.Verify but hashes with the unicode collation + xxhash; any Hash failure (non-bytes-convertible value or invalid UTF-8) is wrapped as 'UnicodeLooseXXHash.Verify: %v'. It means one of the ids supplied for verification cannot be normalized by the unicode collator.","triggerScenarios":"Verify invoked with ids[i] that cannot ToBytes() or contains bytes that are not valid UTF-8, typically while validating vindex ownership during a routed write or VReplication vindex check.","commonSituations":"Non-UTF8 client charset writing to a unicode_loose_xxhash column; binary/blobs mapped to this vindex; corrupted data from direct MySQL writes bypassing VTGate.","solutions":["Find the offending row/value and verify it with a UTF-8 validity check.","Enforce utf8mb4 charset on the column and connections.","Re-encode or clean the invalid data.","Switch the vindex to a hash/binary variant if the data is not really unicode text.","Ensure only string values are supplied to Verify from tooling."],"exampleFix":"// before\nWHERE name = 0xFF -- hex literal on unicode_loose_xxhash vindex\n// after\nWHERE name = 'café' -- valid utf8mb4 string","handlingStrategy":"validation","validationCode":"if !utf8.Valid(idBytes) {\n    return errors.New(\"unicode_loose_xxhash requires valid UTF-8 ids\")\n}","typeGuard":null,"tryCatchPattern":"ok, err := vindex.Verify(ctx, vc, ids, ksids)\nif err != nil {\n    return fmt.Errorf(\"verify failed: %w\", err) // inspect for invalid UTF-8 cause\n}","preventionTips":["Keep vindex columns VARCHAR with utf8mb4","Block hex/binary literals against unicode vindex columns in app validation","Detect corrupted rows with periodic UTF-8 scans","Fix direct-MySQL writes to go through VTGate"],"tags":["vtgate","vindex","utf-8","xxhash"],"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"}