can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: invalid LZX repeated offset
Error message
Invalid CAB archive: invalid LZX repeated offset
What it means
During CAB LZX decompression, the decoder reads the three repeated-offset registers (r0/r1/r2) from the block header. The LZX spec requires all three to be initialized to 1 (nonzero); a zero value means the stream is corrupt or not real LZX data, so ArchiveError is thrown from #readBlockHeader.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:255
for (let index = 0; index < alignedLengths.byteLength; index++) alignedLengths[index] = reader.readBits(3);
this.#alignedTable = new LzxHuffmanTable(alignedLengths);
}
readCodeLengths(reader, this.#mainLengths, 0, 256);
readCodeLengths(reader, this.#mainLengths, 256, this.#mainLengths.byteLength);
this.#mainTable = new LzxHuffmanTable(this.#mainLengths);
if (this.#mainLengths[0xe8] !== 0) this.#intelStarted = true;
readCodeLengths(reader, this.#lengthLengths, 0, this.#lengthLengths.byteLength);
this.#lengthTable = new LzxHuffmanTable(this.#lengthLengths, true);
return;
}
if (this.#blockType === 3) {
this.#intelStarted = true;
reader.alignWord();
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);View on GitHub (pinned to 9690622007)
Solutions
- Verify the CAB file is intact (re-download or re-extract the archive).
- Confirm the folder's compression method is actually LZX and you are passing the correct data slice to decompressFrame.
- Treat the file as corrupt: surface ArchiveError to the caller instead of retrying.
Defensive patterns
Strategy: try-catch
Validate before calling
// heuristic pre-check: CAB folder payload should start with plausible LZX bitstream bytes
function looksLikeLzxPayload(bytes, offset) {
return Number.isInteger(offset) && offset >= 0 && offset + 12 <= bytes.byteLength;
} Type guard
function hasLzxHeaderRoom(bytes, offset) {
return offset + 12 <= bytes.byteLength;
} Try / catch
try {
const out = folder.decompressFrame(frame);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("repeated offset")) {
// report archive as corrupt
} else throw err;
} Prevention
- Verify CAB integrity (checksums) before extraction
- Ensure frames are decompressed sequentially from the first frame
- Only pass LZX-compressed folder data to the LZX decoder
When it happens
Trigger: decompressFrame -> #readBlockHeader parses an LZX block whose header yields r0, r1, or r2 equal to 0 after reading three UInt32LE values.
Common situations: Corrupted or truncated .cab files, wrong offsets into the CAB data (parsing a folder that is not actually LZX-compressed), or hand-crafted/fuzzed archive bytes.
Related errors
- Invalid CAB archive: misaligned LZX byte stream
- Invalid CAB archive: invalid LZX Huffman code length
- Invalid CAB archive: unsupported LZX block type ${this.#bloc
- Invalid CAB archive: LZX match crosses a frame or block boun
- Invalid CAB archive: LZX position slot is out of range
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/42babacfc229ec0c.
Report an issue: GitHub.