vitessio/vitess · error

invalid signature for UcpTrie: 0x%08x

Error message

invalid signature for UcpTrie: 0x%08x

What it means

UcpTrieFromBytes deserializes a precompiled ICU UcpTrie from its binary form and expects the first 4 bytes to be one of the known little-endian signatures (Trie3/Trie4, 0x54726933/0x54726934-style). An unrecognized signature means the byte slice is not a serialized UcpTrie produced by the matching ICU version/format - it is truncated, corrupted, or an entirely different data blob.

Source

Thrown at go/mysql/icuregex/internal/utrie/ucptrie.go:269

		/** Data null block offset bits 15..0, 0xfffff if none. */
		dataNullOffset uint16

		/**
		 * First code point of the single-value range ending with U+10ffff,
		 * rounded up and then shifted right by UCPTRIE_SHIFT_2.
		 */
		shiftedHighStart uint16
	}

	var header ucpHeader
	header.signature = bytes.Uint32()

	switch header.signature {
	case ucpTrieSig:
	case ucpTrieOESig:
		return nil, errors.New("unsupported: BigEndian encoding")
	default:
		return nil, fmt.Errorf("invalid signature for UcpTrie: 0x%08x", header.signature)
	}

	header.options = bytes.Uint16()
	header.indexLength = bytes.Uint16()
	header.dataLength = bytes.Uint16()
	header.index3NullOffset = bytes.Uint16()
	header.dataNullOffset = bytes.Uint16()
	header.shiftedHighStart = bytes.Uint16()

	typeInt := (header.options >> 6) & 3
	valueWidthInt := header.options & optionsValueBitsMask
	if typeInt > uint16(typeSmall) || valueWidthInt > uint16(valueBits8) ||
		(header.options&optionsReservedMask) != 0 {
		return nil, errors.New("invalid options for serialized UcpTrie")
	}
	actualType := ucpTrieType(typeInt)
	actualValueWidth := ucpTrieValueWidth(valueWidthInt)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Regenerate the serialized trie data with the project's codegen (make codegen / the icuregex generation step) so the signature matches what this deserializer expects.
  2. Verify the byte slice is complete and uncorrupted (check length and that the first 4 bytes are the expected little-endian Trie3/Trie4 signature).
  3. If the data was produced by a newer ICU with a changed format, upgrade the internal/utrie deserializer (or pin the ICU codegen version) - note BigEndian-encoded tries are explicitly unsupported and raise a separate error.

Example fix

// before
data := readBundledFile("caseProps.trie") // truncated/corrupt
trie, err := utrie.UcpTrieFromBytes(data)
// after
if len(data) < 4 || binary.LittleEndian.Uint32(data[:4]) != utrie.ExpectedSignature {
    return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "embedded UcpTrie data missing or has invalid signature")
}
trie, err := utrie.UcpTrieFromBytes(data)
Defensive patterns

Strategy: validation

Validate before calling

func validUcpTrieBlob(data []byte) bool {
    if len(data) < 4 {
        return false
    }
    sig := binary.LittleEndian.Uint32(data[:4])
    return sig == utrie.ExpectedLittleEndianSignature // verify against the package's ucpTrieSig constant
}

Try / catch

trie, err := utrie.UcpTrieFromBytes(data)
if err != nil {
    return nil, vterrors.Wrapf(err, vtrpcpb.Code_INTERNAL, "failed to load embedded UcpTrie data (codegen output stale or corrupted)")
}

Prevention

When it happens

Trigger: Calling UcpTrieFromBytes (via load/readData in the icuregex package) with data whose leading uint32 does not match ucpTrieSig, typically because the embedded trie binary is missing, truncated, or was built/serialized by an incompatible ICU or codegen version.

Common situations: Corrupted or partially-copied generated data files in the icuregex internal tables, codegen output from a mismatched ICU version after an ICU upgrade, or a build/packaging issue where the binary asset was replaced or zero-filled.

Related errors


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