can1357/oh-my-pi · error · ArchiveError
Invalid CAB archive: MSZIP decompression failed${error insta
Error message
Invalid CAB archive: MSZIP decompression failed${error instanceof Error ? `: ${error.message}` : ""} What it means
Thrown by CabFolder.#decode when node:zlib's inflateRawSync rejects the deflate stream inside an MSZIP block (after the 'CK' signature). The original zlib error message is appended so you can see the underlying zlib failure (e.g. 'invalid distance too far back', unexpected end of file). MSZIP inflate also receives the previous 32KB of folder output as the dictionary window, so mid-folder failures can indicate missing or wrong preceding data.
Source
Thrown at packages/utils/src/ar/cab.ts:197
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}`,
);
}
output.set(decoded, outputPosition);
outputPosition += decoded.byteLength;
position = payloadEnd;
}
return output;View on GitHub (pinned to 9690622007)
Solutions
- Read the appended zlib message to identify the inflate failure mode
- Re-download/verify the archive with `cabextract -t`; re-obtain if corrupt
- If failure happens deep in a multi-block folder, suspect corruption in an earlier block (it seeds the MSZIP dictionary)
- Regenerate the cabinet with makecab/7-Zip if you control production; otherwise report a bug if cabextract succeeds
Example fix
// before
try { await extractCab(path, dest); } catch { console.log('failed'); }
// after
try { await extractCab(path, dest); }
catch (err) {
if (err instanceof ArchiveError && err.message.includes('MSZIP decompression failed'))
console.error(`archive corrupt at MSZIP block: ${err.message}`);
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
const t = Bun.$`cabextract -t ${path}`.quiet().nothrow();
if ((await t).exitCode !== 0) throw new Error(`corrupt cabinet: ${path}`); Try / catch
try {
await readCab(source, opts);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('MSZIP decompression failed')) {
logger.error('MSZIP inflate failed', { path: archivePath, detail: err.message });
throw new Error(`Archive corrupt at an MSZIP block: ${err.message}`);
}
throw err;
} Prevention
- Log the appended zlib detail — it pinpoints the corruption type
- Re-download rather than retry: deflate corruption is not transient
- For multi-block folders, remember an early bad block poisons later MSZIP dictionary windows
When it happens
Trigger: readCab() indexed a method-1 folder and zlib.inflateRawSync(payload.subarray(2), {dictionary, maxOutputLength}) threw — corrupt deflate stream, wrong dictionary window due to an earlier failed block, or truncated payload.
Common situations: Partially corrupted archives; extracting method-1 cabinets where an earlier block was silently damaged so the 32KB MSZIP history window is wrong; files from unreliable sources.
Related errors
- Invalid CAB archive: MSZIP block is missing its CK signature
- Invalid CAB archive: CFDATA block ${block} produced ${decode
- Invalid ARJ method-4 compressed data: truncated bitstream
- Invalid ARJ method-4 compressed data: non-zero trailing bits
- Invalid ARJ method-4 compressed data: match exceeds declared
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/32b12361d4df7a2f.
Report an issue: GitHub.