can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: missing LZX decode trees
Error message
Invalid CAB archive: missing LZX decode trees
What it means
#decodeRun tries to Huffman-decode symbols but the main and length decode trees were never built (a Verbatim/Aligned block header was not parsed for this block). This indicates internal state misuse or a corrupt stream where block setup was skipped.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:269
this.#r0 = reader.readUInt32LE();
this.#r1 = reader.readUInt32LE();
this.#r2 = reader.readUInt32LE();
if (this.#r0 === 0 || this.#r1 === 0 || this.#r2 === 0) {
throw new ArchiveError("Invalid CAB archive: invalid LZX repeated offset");
}
this.#uncompressedPadding = (this.#blockLength & 1) !== 0;
return;
}
throw new ArchiveError(`Invalid CAB archive: unsupported LZX block type ${this.#blockType}`);
}
#decodeRun(reader: LzxBitReader, output: Uint8Array, outputStart: number, count: number): number {
if (this.#blockType === 3) {
for (let index = 0; index < count; index++) this.#writeByte(reader.readByte(), output, outputStart + index);
return count;
}
if (!this.#mainTable || !this.#lengthTable)
throw new ArchiveError("Invalid CAB archive: missing LZX decode trees");
let produced = 0;
while (produced < count) {
const element = this.#mainTable.decode(reader);
if (element < 256) {
this.#writeByte(element, output, outputStart + produced);
produced++;
continue;
}
const match = element - 256;
let matchLength = match & NUM_PRIMARY_LENGTHS;
if (matchLength === NUM_PRIMARY_LENGTHS) matchLength += this.#lengthTable.decode(reader);
matchLength += MIN_MATCH;
if (matchLength > count - produced || matchLength > this.#blockRemaining - produced) {
throw new ArchiveError("Invalid CAB archive: LZX match crosses a frame or block boundary");
}
View on GitHub (pinned to 9690622007)
Solutions
- Ensure decompressFrame is used end-to-end rather than invoking internal decode pieces directly.
- Validate the archive; if the header parsed but trees are missing, the stream is corrupt.
- Re-obtain the archive from a trusted source.
Defensive patterns
Strategy: try-catch
Try / catch
try {
const out = decompressFrame(frame);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("missing LZX decode trees")) {
// stream state desync — mark archive corrupt
} else throw err;
} Prevention
- Use only the public decompressFrame API, not internal decode helpers
- Decompress complete frames; never skip block headers
- Validate archive integrity before decoding
When it happens
Trigger: decompressFrame -> #decodeRun called with blockType 1 or 2 while #mainTable or #lengthTable is null (trees not initialized via #readBlockHeader).
Common situations: A CAB payload whose block header parsing diverged earlier (bad block type/length) leaving trees unset; calling low-level decode APIs out of order.
Related errors
- Invalid CAB archive: missing LZX aligned tree
- Invalid CAB archive: truncated LZX bitstream
- Invalid CAB archive: misaligned LZX byte stream
- Invalid CAB archive: truncated LZX data
- Invalid CAB archive: invalid LZX Huffman code length
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5890db64a27d219b.
Report an issue: GitHub.