can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: LZX match offset exceeds available hist
Error message
Invalid CAB archive: LZX match offset exceeds available history
What it means
The decoded match offset is zero or larger than the bytes decoded so far / window size, so the copy would read before the start of the output history. This is a definitive corruption signal in the LZX bitstream.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:318
} else {
if (slot >= this.#positionBase.byteLength)
throw new ArchiveError("Invalid CAB archive: LZX position slot is out of range");
const extra = this.#extraBits[slot]!;
matchOffset = this.#positionBase[slot]! - 2;
if (this.#blockType === 2 && extra >= 3) {
if (extra > 3) matchOffset += reader.readBits(extra - 3) * 8;
if (!this.#alignedTable) throw new ArchiveError("Invalid CAB archive: missing LZX aligned tree");
matchOffset += this.#alignedTable.decode(reader);
} else if (extra !== 0) {
matchOffset += reader.readBits(extra);
}
this.#r2 = this.#r1;
this.#r1 = this.#r0;
this.#r0 = matchOffset;
}
if (matchOffset <= 0 || matchOffset > Math.min(this.#decodedSize, this.#window.byteLength)) {
throw new ArchiveError("Invalid CAB archive: LZX match offset exceeds available history");
}
for (let index = 0; index < matchLength; index++) {
const source = (this.#windowPosition - matchOffset + this.#window.byteLength) % this.#window.byteLength;
this.#writeByte(this.#window[source]!, output, outputStart + produced + index);
}
produced += matchLength;
}
return produced;
}
#writeByte(value: number, output: Uint8Array, outputPosition: number): void {
output[outputPosition] = value;
this.#window[this.#windowPosition] = value;
this.#windowPosition = (this.#windowPosition + 1) % this.#window.byteLength;
this.#decodedSize++;
}
#translateE8(raw: Uint8Array): Uint8Array {View on GitHub (pinned to 9690622007)
Solutions
- Re-obtain the CAB from a trusted source.
- Confirm you decompress frames in order from the first frame; LZX history depends on all prior output.
- Catch ArchiveError and report the file as corrupt.
Defensive patterns
Strategy: try-catch
Try / catch
try {
const out = decompressFrame(frame);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("exceeds available history")) {
// corrupt back-reference — abort and report
} else throw err;
} Prevention
- Decompress frames strictly in order so history is complete
- Reject archives failing checksum verification
- Treat any ArchiveError during LZX decode as terminal
When it happens
Trigger: decompressFrame -> #decodeRun resolves a matchOffset <= 0 or > min(decodedSize, window.byteLength) before copying matchLength bytes from the ring window.
Common situations: Truncated or corrupted CAB extraction, wrong start offset into compressed data, fuzzed inputs.
Related errors
- Invalid CAB archive: misaligned LZX byte stream
- Invalid CAB archive: invalid LZX Huffman code length
- Invalid CAB archive: invalid LZX repeated offset
- Invalid CAB archive: unsupported LZX block type ${this.#bloc
- Invalid CAB archive: LZX match crosses a frame or block boun
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f7eb14392083e079.
Report an issue: GitHub.