vitessio/vitess · error
invalid signature for Trie2: 0x%08x
Error message
invalid signature for Trie2: 0x%08x
What it means
UTrie2FromBytes rejects serialized Unicode Trie2 (UTrie2) data whose leading 4-byte signature/magic does not match the expected 'Tri2' (0x54726932) value. This guards the deserializer in go/mysql/icuregex/internal/utrie/utrie2.go against parsing random or corrupted bytes as a case-mapping trie. Big-endian ('2irT', 0x32697254) is recognized but explicitly unsupported and yields a different error.
Source
Thrown at go/mysql/icuregex/internal/utrie/utrie2.go:381
/** Null index and data blocks, not shifted. */
index2NullOffset, dataNullOffset uint16
/**
* First code point of the single-value range ending with U+10ffff,
* rounded up and then shifted right by UTRIE2_SHIFT_1.
*/
shiftedHighStart uint16
}
var header utrie2Header
header.signature = bytes.Uint32()
switch header.signature {
case 0x54726932:
case 0x32697254:
return nil, errors.New("unsupported: BigEndian encoding")
default:
return nil, fmt.Errorf("invalid signature for Trie2: 0x%08x", header.signature)
}
header.options = bytes.Uint16()
header.indexLength = bytes.Uint16()
header.shiftedDataLength = bytes.Uint16()
header.index2NullOffset = bytes.Uint16()
header.dataNullOffset = bytes.Uint16()
header.shiftedHighStart = bytes.Uint16()
var width int
switch header.options & 0xf {
case 0:
width = 16
case 1:
width = 32
default:
return nil, errors.New("invalid width for serialized UTrie2")
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Verify the byte slice passed to UTrie2FromBytes starts exactly at the trie header with the 4-byte magic 0x54726932 ('Tri2' little-endian)
- Regenerate the ICU/trie data with the standard tooling so it is serialized little-endian, and re-embed it
- Check that any preceding header fields consumed by readData (options/lengths) were not skipped, shifting the read offset
- If the source data is big-endian (0x32697254), convert it to little-endian — the parser rejects big-endian outright
Example fix
// before: slicing from the start of the file trie, err := utrie2.UTrie2FromBytes(blob) // after: skip the file header to the trie data section trie, err := utrie2.UTrie2FromBytes(blob[headerLen:])
Defensive patterns
Strategy: validation
Validate before calling
func validTrie2(b []byte) bool {
return len(b) >= 4 && binary.LittleEndian.Uint32(b) == 0x54726932
}
if !validTrie2(data) { return errors.New("not a little-endian Trie2 blob") } Type guard
func isTrie2Data(b []byte) bool {
return len(b) >= 4 && string(b[0:4]) == "Tri2"
} Prevention
- Check the first 4 bytes of the blob for 0x54726932 before deserializing
- Regenerate trie data only with the project's standard little-endian tooling
- Pin/verify checksums of embedded ICU data blobs in CI
- Log the signature value (hex) when deserialization fails to spot endianness vs offset issues
When it happens
Trigger: Calling UTrie2FromBytes (via readData) with data whose first 4 bytes are not 0x54726932 — e.g. a truncated or corrupt embedded ICU data blob, wrong offset into the byte slice, a big-endian serialized trie, or passing entirely unrelated bytes.
Common situations: Regenerating or replacing ICU data files with a different tool/version that emits big-endian output; manual slicing of the data section at a wrong offset; corrupted binary blobs embedded in a build; porting data from another ICU distribution.
Related errors
- cannot marshal data: %v
- protojson error: %v
- json error: %v
- panic(err)
- ReadFile cannot be called on read-write backup
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/0cf781fcea1d5381.
Report an issue: GitHub.