can1357/oh-my-pi · error · ArchiveError

Invalid CAB archive: MSZIP block is missing its CK signature

Error message

Invalid CAB archive: MSZIP block is missing its CK signature

What it means

Thrown by CabFolder.#decode when the folder's compression method is 1 (MSZIP) but the block payload does not begin with the two-byte 'CK' (0x43 0x4B) magic signature that the MSZIP format requires before the raw deflate stream. Without it the payload cannot be a valid MSZIP block.

Source

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

		const output = new Uint8Array(outputSize);
		const lzx = description.method === 3 ? new LzxDecoder(description.parameter) : undefined;
		position = 0;
		let outputPosition = 0;
		for (let block = 0; block < description.blockCount; block++) {
			const compressed = readUInt16LE(bytes, position + 4);
			const uncompressed = readUInt16LE(bytes, position + 6);
			const payloadStart = position + DATA_BLOCK_SIZE + this.#dataReserveSize;
			const payloadEnd = payloadStart + compressed;
			const payload = bytes.subarray(payloadStart, payloadEnd);
			let decoded: Uint8Array;
			if (description.method === 0) {
				if (compressed !== uncompressed) {
					throw new ArchiveError("Invalid CAB archive: uncompressed CFDATA sizes do not match");
				}
				decoded = payload;
			} else if (description.method === 1) {
				if (payload.byteLength < 2 || payload[0] !== 0x43 || payload[1] !== 0x4b) {
					throw new ArchiveError("Invalid CAB archive: MSZIP block is missing its CK signature");
				}
				try {
					const dictionary = output.subarray(Math.max(0, outputPosition - MAX_DATA_OUTPUT), outputPosition);
					decoded = new Uint8Array(
						zlib.inflateRawSync(payload.subarray(2), { dictionary, maxOutputLength: uncompressed }),
					);
				} catch (error) {
					throw new ArchiveError(
						`Invalid CAB archive: MSZIP decompression failed${error instanceof Error ? `: ${error.message}` : ""}`,
					);
				}
			} else {
				decoded = lzx!.decompressFrame(payload, uncompressed);
			}
			if (decoded.byteLength !== uncompressed) {
				throw new ArchiveError(
					`Invalid CAB archive: CFDATA block ${block} produced ${decoded.byteLength} bytes, expected ${uncompressed}`,
				);

View on GitHub (pinned to 9690622007)

Solutions

  1. Confirm corruption with `cabextract -t file.cab`; re-download if it fails
  2. Check the CFFOLDER compression type byte — if the data is actually stored or LZX, a corrupted type field can masquerade as MSZIP
  3. Regenerate the cabinet with a standard tool if you control its creation
  4. If cabextract reads it fine, file a reader bug with a minimal repro
Defensive patterns

Strategy: try-catch

Validate before calling

const head = new Uint8Array(await Bun.file(path).slice(0, 4).arrayBuffer());
if (!sniffCab(head)) throw new Error(`not a CAB archive: ${path}`);
// deeper structure is validated by the reader itself

Try / catch

try {
  await readCab(source, opts);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('missing its CK signature'))
    throw new Error('Cabinet MSZIP block is corrupt or the compression-type field is damaged.');
  throw err;
}

Prevention

When it happens

Trigger: readCab() indexed a method-1 folder whose CFDATA payload is shorter than 2 bytes or does not start with 'CK'; caused by corruption, wrong compression method declared in CFFOLDER, or a non-conforming writer.

Common situations: Corrupted downloads; cabinets whose folder compression type field was damaged; files produced by broken third-party archivers.

Related errors


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