can1357/oh-my-pi · error · ArchiveError
Unsupported CAB LZX window size: ${windowBits} bits (expecte
Error message
Unsupported CAB LZX window size: ${windowBits} bits (expected 15-21) What it means
The LzxDecoder constructor only supports CAB LZX window sizes from 2^15 (32 KiB) to 2^21 (2 MiB) bits, as used by CAB folders (the cabinet format stores the window bits minus 15 in the folder header). Passing a non-integer or out-of-range windowBits is rejected before any allocation, since the position-slot tables are only defined for 15-21.
Source
Thrown at packages/utils/src/ar/codecs/lzx.ts:176
#lengthTable?: LzxHuffmanTable;
#alignedTable?: LzxHuffmanTable;
#windowPosition = 0;
#decodedSize = 0;
#frame = 0;
#r0 = 1;
#r1 = 1;
#r2 = 1;
#headerRead = false;
#intelFileSize = 0;
#intelStarted = false;
#blockType = 0;
#blockLength = 0;
#blockRemaining = 0;
#uncompressedPadding = false;
constructor(windowBits: number) {
if (!Number.isInteger(windowBits) || windowBits < 15 || windowBits > 21) {
throw new ArchiveError(`Unsupported CAB LZX window size: ${windowBits} bits (expected 15-21)`);
}
this.#window = new Uint8Array(2 ** windowBits);
const slots = POSITION_SLOTS[windowBits - 15]!;
this.#mainLengths = new Uint8Array(256 + slots * 8);
this.#extraBits = new Uint8Array(slots);
this.#positionBase = new Uint32Array(slots);
for (let slot = 0; slot < slots; slot++) {
this.#extraBits[slot] = slot < 4 ? 0 : Math.min(17, Math.floor(slot / 2) - 1);
if (slot > 0) this.#positionBase[slot] = this.#positionBase[slot - 1]! + 2 ** this.#extraBits[slot - 1]!;
}
}
/** Decode one CAB CFDATA LZX frame while preserving the folder's dictionary and Huffman state. */
decompressFrame(bytes: Uint8Array, outputSize: number): Uint8Array {
if (!Number.isInteger(outputSize) || outputSize < 0 || outputSize > FRAME_SIZE) {
throw new ArchiveError(`Invalid CAB archive: LZX frame size ${outputSize} exceeds 32768 bytes`);
}
if (outputSize === 0) return new Uint8Array(0);View on GitHub (pinned to 9690622007)
Solutions
- Pass windowBits = rawHeaderValue + 15 when reading a CAB folder header (the stored value is 0-6).
- Clamp or validate windowBits to an integer 15-21 before constructing.
- If the stream is not CAB LZX, use a decoder for that container's LZX variant instead.
- Default to 15 (32 KiB) only when the format genuinely omits the field.
Example fix
// before const decoder = new LzxDecoder(folder.compressionMemory) // after const decoder = new LzxDecoder(folder.windowBits + 15) // header stores windowBits - 15 (0..6)
Defensive patterns
Strategy: validation
Validate before calling
function toWindowBits(storedBits: number): number {
const windowBits = storedBits + 15 // CAB folder header stores windowBits - 15
if (!Number.isInteger(windowBits) || windowBits < 15 || windowBits > 21) {
throw new Error(`Invalid window bits ${storedBits} in CAB folder header`)
}
return windowBits
}
const decoder = new LzxDecoder(toWindowBits(folder.headerValue)) Type guard
function isValidWindowBits(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 15 && v <= 21
} Try / catch
try {
const decoder = new LzxDecoder(folder.windowBits + 15)
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('window size')) {
throw new Error(`Unsupported CAB LZX window bits in folder header: ${folder.windowBits}`)
}
throw err
} Prevention
- Remember CAB stores windowBits - 15 (values 0-6); add 15 before constructing
- Validate the folder header field before instantiating the decoder
- Use CAB LZX only for CAB-originated streams; other LZX variants differ
When it happens
Trigger: new LzxDecoder(14), new LzxDecoder(22), new LzxDecoder(16.5), or new LzxDecoder(NaN) — typically from misreading the CAB folder header's window bits field, which is stored as (windowBits - 15).
Common situations: Passing the raw folder-header byte instead of adding 15, feeding LZX streams from other container formats (e.g. MSI/DIET variants) that use different window conventions, typos in configuration.
Understand the failure class
Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.
Related errors
- Invalid CAB archive: LZX frame size ${outputSize} exceeds 32
- Invalid CAB archive: truncated data
- Invalid CAB archive: file has an invalid DOS timestamp
- Unsupported CAB LZX window size: ${description.parameter} bi
- Invalid CAB archive: CFDATA expands to ${uncompressed} bytes
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/29504d0046bb4b27.
Report an issue: GitHub.