can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: empty LZX Huffman tree
Error message
Invalid CAB archive: empty LZX Huffman tree
What it means
This error is thrown by the LzxHuffmanTable constructor when every code length in the tree description is zero, i.e. no symbols are assigned any Huffman code. The LZX format requires a usable tree to decode the bitstream, so a tree with zero symbols is rejected unless the caller explicitly passes allowEmpty (used only for the length tree, which may legitimately be empty). It guards against corrupted or malformed CAB LZX block headers.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:80
class LzxHuffmanTable {
readonly #counts = new Uint32Array(17);
readonly #firstCodes = new Uint32Array(17);
readonly #firstSymbols = new Uint32Array(17);
readonly #symbols: Uint16Array;
readonly empty: boolean;
constructor(lengths: Uint8Array, allowEmpty = false) {
let symbolCount = 0;
for (const length of lengths) {
if (length > 16) throw new ArchiveError("Invalid CAB archive: invalid LZX Huffman code length");
if (length !== 0) {
this.#counts[length]++;
symbolCount++;
}
}
this.empty = symbolCount === 0;
if (this.empty && !allowEmpty) {
throw new ArchiveError("Invalid CAB archive: empty LZX Huffman tree");
}
let code = 0;
let symbolOffset = 0;
for (let length = 1; length <= 16; length++) {
code = (code + this.#counts[length - 1]!) * 2;
if (code + this.#counts[length]! > 2 ** length) {
throw new ArchiveError("Invalid CAB archive: oversubscribed LZX Huffman tree");
}
this.#firstCodes[length] = code;
this.#firstSymbols[length] = symbolOffset;
symbolOffset += this.#counts[length]!;
}
this.#symbols = new Uint16Array(symbolCount);
const next = this.#firstSymbols.slice();
for (let symbol = 0; symbol < lengths.byteLength; symbol++) {
const length = lengths[symbol]!;View on GitHub (pinned to 9690622007)
Solutions
- Verify the CAB file integrity (checksums, re-download or re-extract the archive).
- Re-create the CAB with a conformant tool (e.g. makecab/cabarc) so each Huffman tree defines at least one symbol.
- If you are constructing trees manually for testing, pass allowEmpty=true or give at least one symbol a non-zero code length.
- Check that the bit reader is synchronized — an earlier parsing mistake can shift bits so zero lengths are read.
Example fix
// before new LzxHuffmanTable(lengths) // throws when all lengths are 0 // after new LzxHuffmanTable(lengths, lengths === this.#lengthLengths) // allow empty only for the secondary length tree
Defensive patterns
Strategy: try-catch
Validate before calling
// If you control the lengths, pre-check before constructing:
const hasSymbol = lengths.some(l => l !== 0)
if (!hasSymbol) throw new Error('Refusing to build an empty Huffman tree') Type guard
function isNonEmptyTree(lengths: Uint8Array): boolean {
return lengths.some(l => l !== 0)
} Try / catch
try {
const table = new LzxHuffmanTable(lengths)
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('empty LZX Huffman tree')) {
// treat archive as corrupt: surface a user-friendly 'archive is damaged' error
}
throw err
} Prevention
- Always feed complete, in-order CFDATA block bytes to the decoder
- Validate CAB checksums before decompression
- Only pass allowEmpty=true for the secondary length tree, as the library itself does
- Re-download rather than retry-decode corrupt archives
When it happens
Trigger: Decompressing a CAB folder whose LZX block header defines a main, length, aligned-offset, or pretree where all code lengths read from the bitstream are 0 (e.g. new LzxHuffmanTable(new Uint8Array(256)) without allowEmpty).
Common situations: Corrupted or truncated CAB downloads, archives produced by buggy or non-conforming LZX compressors, bit-level parsing desync from an earlier bad read leaving garbage where tree lengths should be.
Related errors
- Invalid CAB archive: oversubscribed LZX Huffman tree
- Invalid CAB archive: invalid LZX Huffman symbol
- Invalid CAB archive: LZX code-length run exceeds its tree
- Invalid CAB archive: invalid LZX Huffman code length
- Invalid CAB archive: LZX stream uses an empty Huffman tree
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/49847a5e534c3029.
Report an issue: GitHub.