{"record":{"id":"73753c50ff825061","repo":"vitessio/vitess","slug":"unicodeloosemd5-map-v","errorCode":null,"errorMessage":"UnicodeLooseMD5.Map: %v","messagePattern":"UnicodeLooseMD5\\.Map: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/vindexes/unicodeloosemd5.go","lineNumber":91,"sourceCode":"func (vind *UnicodeLooseMD5) 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(\"UnicodeLooseMD5.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 *UnicodeLooseMD5) 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(\"UnicodeLooseMD5.Map: %v\", err)\n\t\t}\n\t\tout = append(out, key.DestinationKeyspaceID(data))\n\t}\n\treturn out, nil\n}\n\nfunc (vind *UnicodeLooseMD5) Hash(id sqltypes.Value) ([]byte, error) {\n\treturn unicodeHash(&collateMD5, id)\n}\n\n// UnknownParams implements the ParamValidating interface.\nfunc (vind *UnicodeLooseMD5) UnknownParams() []string {\n\treturn vind.unknownParams\n}\n\nfunc init() {\n\tRegister(\"unicode_loose_md5\", newUnicodeLooseMD5)\n}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/vindexes/unicodeloosemd5.go#L73-L109","documentation":"UnicodeLooseMD5.Map maps each id to a shard DestinationKeyspaceID by hashing it with the collation-normalized MD5; it wraps any Hash failure in 'UnicodeLooseMD5.Map: %v'. The underlying unicodeHash fails only if the value cannot be converted to bytes or contains invalid UTF-8. This error aborts routing: VTGate cannot determine the destination shard for the offending row.","triggerScenarios":"Any query whose WHERE clause / insert row uses the unicode_loose_md5 vindexed column with a value that is not valid UTF-8 or cannot be reduced to bytes (e.g. NULL tuple value, binary-typed bind var).","commonSituations":"Application sending binary or non-UTF8-encoded strings (wrong connection charset); schema changed column to a binary type; ETL jobs writing legacy-encoded data; tools building sqltypes.Value from raw bytes.","solutions":["Log/capture the offending value from the failing query and check its encoding with a UTF-8 validator.","Set the client connection charset to utf8mb4 so string literals arrive as valid UTF-8.","Fix or re-encode the bad rows/data at the source before retrying the query.","Change the column charset to utf8mb4 or choose a binary vindex if the data is inherently non-unicode.","If it is a programmatic caller, pass plain string sqltypes.Value values, not tuple/expression values."],"exampleFix":"// before\nINSERT INTO t (name) VALUES (UNHEX('FF')); -- invalid UTF-8 hits unicode_loose_md5 vindex\n// after\nINSERT INTO t (name) VALUES ('café'); -- valid utf8mb4, or switch vindex to binary_md5 for raw bytes","handlingStrategy":"validation","validationCode":"if !utf8.ValidString(val) {\n    return fmt.Errorf(\"value %q is not valid UTF-8 for unicode_loose_md5 vindex\", val)\n}","typeGuard":null,"tryCatchPattern":"dest, err := vindex.Map(ctx, vc, ids)\nif err != nil {\n    log.Warn(\"map failed\", slog.Any(\"error\", err))\n    return err // query cannot be routed; surface to client\n}","preventionTips":["SET NAMES utf8mb4 on all client connections","Run charset checks in CI against vindex-backed columns","Convert legacy latin1 data before adding the vindex","Prefer binary_md5/hash for opaque byte identifiers"],"tags":["vtgate","vindex","utf-8","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"}