can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: LZX code-length run exceeds its tree
Error message
Invalid CAB archive: LZX code-length run exceeds its tree
What it means
Thrown by readCodeLengths when a pretree symbol 17 or 18 (zero-run of length 4-19 or 20-51) would extend past the last tree index being defined. The run would write outside the tree's declared symbol range, so the block header is malformed.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:127
const relative = code - this.#firstCodes[length]!;
if (relative >= 0 && relative < this.#counts[length]!) {
return this.#symbols[this.#firstSymbols[length]! + relative]!;
}
}
throw new ArchiveError("Invalid CAB archive: invalid LZX Huffman symbol");
}
}
function readCodeLengths(reader: LzxBitReader, lengths: Uint8Array, first: number, last: number): void {
const pretreeLengths = new Uint8Array(20);
for (let index = 0; index < pretreeLengths.byteLength; index++) pretreeLengths[index] = reader.readBits(4);
const pretree = new LzxHuffmanTable(pretreeLengths);
let index = first;
while (index < last) {
const symbol = pretree.decode(reader);
if (symbol === 17 || symbol === 18) {
const run = reader.readBits(symbol === 17 ? 4 : 5) + (symbol === 17 ? 4 : 20);
if (index + run > last) throw new ArchiveError("Invalid CAB archive: LZX code-length run exceeds its tree");
lengths.fill(0, index, index + run);
index += run;
continue;
}
if (symbol === 19) {
const run = reader.readBits(1) + 4;
if (index + run > last) throw new ArchiveError("Invalid CAB archive: LZX code-length run exceeds its tree");
const delta = pretree.decode(reader);
const length = (lengths[index]! - delta + 17) % 17;
lengths.fill(length, index, index + run);
index += run;
continue;
}
lengths[index] = (lengths[index]! - symbol + 17) % 17;
index++;
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Verify CAB integrity and re-obtain the archive.
- Recompress with a standard tool so code-length runs fit the tree bounds.
- Check the block header bit position; earlier desync turns ordinary symbols into spurious run codes.
Defensive patterns
Strategy: try-catch
Try / catch
try {
decoder.decompressFrame(bytes, size)
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('code-length run exceeds')) {
throw new Error('CAB archive corrupt: malformed block header')
}
throw err
} Prevention
- Validate archive integrity before decoding
- Do not attempt partial resync after bitstream errors — restart the folder decode
- Prefer archives produced by standard tools (makecab/cabarc/7-Zip)
When it happens
Trigger: Decoding a Verbatim (type 1) or Aligned (type 2) LZX block where an encoded zero-run near the end of the main/length/aligned tree description claims more trailing zeros than remain between first and last.
Common situations: Corrupted CAB archives, compressors emitting run lengths that overrun the tree size, bit desync causing a normal symbol to be misread as a run symbol.
Related errors
- Invalid CAB archive: empty LZX Huffman tree
- Invalid CAB archive: oversubscribed LZX Huffman tree
- Invalid CAB archive: invalid LZX Huffman symbol
- 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/613a78f6034b9ce1.
Report an issue: GitHub.