can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: truncated LZX data
Error message
Invalid CAB archive: truncated LZX data
What it means
readByte() found the input exhausted while reading a raw byte (uncompressed block data, padding byte, or 32-bit repeated-offset values). Unlike the bitstream truncation error, this fires on byte-aligned reads: the buffer passed to decompressFrame() is shorter than the block headers and raw data inside it require.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:48
}
const take = Math.min(needed, this.#remaining);
value = value * 2 ** take + ((this.#word >>> (this.#remaining - take)) & (2 ** take - 1));
this.#remaining -= take;
needed -= take;
}
return value;
}
alignWord(): void {
this.#remaining = 0;
}
readByte(): number {
if (this.#remaining !== 0) {
throw new ArchiveError("Invalid CAB archive: misaligned LZX byte stream");
}
if (this.#offset >= this.#bytes.byteLength) {
throw new ArchiveError("Invalid CAB archive: truncated LZX data");
}
return this.#bytes[this.#offset++]!;
}
readUInt32LE(): number {
const b0 = this.readByte();
const b1 = this.readByte();
const b2 = this.readByte();
const b3 = this.readByte();
return (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)) >>> 0;
}
}
class LzxHuffmanTable {
readonly #counts = new Uint32Array(17);
readonly #firstCodes = new Uint32Array(17);
readonly #firstSymbols = new Uint32Array(17);
readonly #symbols: Uint16Array;View on GitHub (pinned to 9690622007)
Solutions
- Pass exactly cbCompressed bytes of the CFDATA block; verify cbCompressed is large enough for uncompressed blocks (padding + blockLength bytes).
- Re-download/re-extract the CAB and validate with cabextract or 7z to rule out simple truncation.
- Audit the caller's block iteration: each folder's cfdata blocks must be fed contiguously with correct sizes to one LzxDecoder instance.
- If parsing CAB yourself, check for reserved-area/CFDATA offset handling errors that make you slice the wrong region.
Example fix
// before
const block = data.subarray(offset, offset + 4096); // arbitrary chunk
const out = decoder.decompressFrame(block, 32768);
// after
const size = cfdatum.cbCompressed;
if (offset + size > data.byteLength) throw new Error("cab truncated");
const out = decoder.decompressFrame(data.subarray(offset, offset + size), cfdatum.cbUncompressed); Defensive patterns
Strategy: validation
Validate before calling
const end = offset + cfdatum.cbCompressed;
if (end > data.byteLength) throw new Error("CAB data truncated");
// uncompressed LZX blocks need padding + blockLength raw bytes inside cbCompressed
if (cfdatum.cbCompressed < cfdatum.cbUncompressed) throw new Error("cbCompressed < cbUncompressed on LZX folder — parser bug"); Type guard
function canReadBytes(data: Uint8Array, offset: number, count: number): boolean {
return count >= 0 && offset >= 0 && offset + count <= data.byteLength;
} Try / catch
try {
return decoder.decompressFrame(frameBytes, outputSize);
} catch (e) {
if (e instanceof Error && e.message.includes("truncated LZX data")) {
throw new Error("Ran out of CFDATA bytes mid-block — CAB truncated or block sizes misparsed");
}
throw e;
} Prevention
- Respect cbCompressed for raw reads; uncompressed blocks still consume padding bits/bytes.
- Validate the CAB with a reference extractor before feeding hand-parsed blocks to the decoder.
- Detect truncation up front: every CFDATA offset+size must fit within the file.
When it happens
Trigger: Calling decompressFrame with a CFDATA block containing a type-3 (uncompressed) block whose stored bytes extend past the buffer end: cbCompressed smaller than the actual block content, subarray cut mid-block, or a corrupt blockLength (up to 65535) that overruns the frame data.
Common situations: Truncated .cab downloads; CAB parsers that mis-handle uncompressed LZX blocks (they store 12 padding bits plus raw bytes, changing the length accounting); passing the wrong block's size fields to the decoder.
Related errors
- Invalid CAB archive: truncated LZX bitstream
- Invalid CAB archive: truncated CFDATA payload
- Invalid CAB archive: misaligned LZX byte stream
- Invalid CAB archive: invalid LZX Huffman code length
- Invalid CAB archive: empty LZX Huffman tree
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/529317f09df7768b.
Report an issue: GitHub.