can1357/oh-my-pi · error · ArchiveError

Unsupported CAB LZX window size: ${description.parameter} bi

Error message

Unsupported CAB LZX window size: ${description.parameter} bits (expected 15-21)

What it means

LZX (method 3) is supported only with window sizes of 15 to 21 bits, matching the CAB spec's legal LZX window range. A CFFOLDER whose data block's parameter (window bits) falls outside 15–21 is rejected before decoding. This protects the decoder from allocating absurd or invalid windows.

Source

Thrown at packages/utils/src/ar/cab.ts:136

		this.#dataReserveSize = dataReserveSize;
		this.#limits = limits;
	}

	readAll(): Promise<Uint8Array> {
		this.#decoded ??= this.#decode();
		return this.#decoded;
	}

	async #decode(): Promise<Uint8Array> {
		const description = this.#description;
		if (description.method === 2) {
			throw new ArchiveError(`Unsupported CAB compression method: Quantum (level ${description.parameter})`);
		}
		if (description.method > 3) {
			throw new ArchiveError(`Unsupported CAB compression method: ${description.method}`);
		}
		if (description.method === 3 && (description.parameter < 15 || description.parameter > 21)) {
			throw new ArchiveError(`Unsupported CAB LZX window size: ${description.parameter} bits (expected 15-21)`);
		}

		const compressedSize = description.dataEnd - description.dataStart;
		assertInMemorySize(compressedSize, this.#limits);
		const bytes = await readExact(this.#source, description.dataStart, description.dataEnd);
		let position = 0;
		let outputSize = 0;
		for (let block = 0; block < description.blockCount; block++) {
			if (position + DATA_BLOCK_SIZE + this.#dataReserveSize > bytes.byteLength) {
				throw new ArchiveError("Invalid CAB archive: truncated CFDATA header");
			}
			const compressed = readUInt16LE(bytes, position + 4);
			const uncompressed = readUInt16LE(bytes, position + 6);
			if (uncompressed === 0) throw new ArchiveError("Unsupported multi-volume CAB archive: split CFDATA block");
			if (uncompressed > MAX_DATA_OUTPUT) {
				throw new ArchiveError(`Invalid CAB archive: CFDATA expands to ${uncompressed} bytes (maximum 32768)`);
			}
			const payloadStart = position + DATA_BLOCK_SIZE + this.#dataReserveSize;

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-pack the archive with standard LZX settings (window 15–21 bits) or fall back to Deflate: recreate with lcab/MSZIP.
  2. Confirm with `cabextract -t file.cab` whether cabextract can read it — if yes, the file is fine but out-of-spec for this library; extract externally and repackage.
  3. Hex-dump the CFFOLDER to verify the parameter byte; a single flipped bit implies corruption — re-transfer.
  4. If producing CABs yourself, ensure your LZX compressor is configured for window ≤ 2^21 bytes.
  5. As an escape hatch, extract with 7z/cabextract and process the plain files instead of the CAB in-process.

Example fix

// before: out-of-spec LZX window
await openCab('odd.cab').then(r => r.readAll()); // Unsupported CAB LZX window size: 30 bits
// after: re-pack with default settings
lcab out/ repacked.cab
await openCab('repacked.cab').then(r => r.readAll());
Defensive patterns

Strategy: validation

Validate before calling

const { method, parameter } = readFolderCompression(cabBytes);
if (method === 3 && (parameter < 15 || parameter > 21))
  throw new Error(`LZX window ${parameter} bits is out of spec (15-21) — re-pack the CAB`);

Type guard

function isValidLzxWindow(p: number): boolean {
  return Number.isInteger(p) && p >= 15 && p <= 21;
}

Try / catch

try {
  return await readCabArchive(bytes);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('LZX window size')) {
    throw new Error('CAB uses an out-of-spec LZX window — re-pack or extract with cabextract');
  }
  throw err;
}

Prevention

When it happens

Trigger: readAll() on a CAB whose LZX folder declares a window size parameter < 15 or > 21 in its CFDATA/lzx parameter field.

Common situations: Corrupted typeCompress/parameter bytes in the folder header; nonstandard LZX writers using out-of-spec window bits; crafted archives probing for decoder bugs; tools that stored a quantum-level value in the LZX parameter field by mistake.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/188e49132e12dead. Report an issue: GitHub.