can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: footer CRC32 mismatch
Error message
Invalid XZ stream: footer CRC32 mismatch
What it means
The XZ stream footer stores a CRC32 of its stream-flag bytes plus the backward-index size. discoverStreams() recomputes the CRC32 over footer bytes 4..10 and compares it to the stored value; a mismatch means the footer (or its CRC field) was modified or corrupted, so the stream cannot be trusted.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:122
function discoverStreams(bytes: Uint8Array): XzStream[] {
if (bytes.byteLength === 0 || (bytes.byteLength & 3) !== 0)
throw new ArchiveError("Invalid XZ stream: size is not a multiple of four bytes");
const streams: XzStream[] = [];
let end = bytes.byteLength;
while (end > 0) {
let padding = 0;
while (end >= 4 && bytes[end - 1] === 0 && bytes[end - 2] === 0 && bytes[end - 3] === 0 && bytes[end - 4] === 0) {
end -= 4;
padding += 4;
}
if (end === 0) throw new ArchiveError("Invalid XZ stream: padding without a stream");
if (end < 24) throw new ArchiveError("Invalid XZ stream: truncated stream framing");
const footerStart = end - 12;
if (bytes[footerStart + 10] !== 0x59 || bytes[footerStart + 11] !== 0x5a)
throw new ArchiveError("Invalid XZ stream: footer magic mismatch");
if (crc32(bytes.subarray(footerStart + 4, footerStart + 10)) !== read32LE(bytes, footerStart))
throw new ArchiveError("Invalid XZ stream: footer CRC32 mismatch");
const flag0 = bytes[footerStart + 8]!;
const flag1 = bytes[footerStart + 9]!;
if (flag0 !== 0 || (flag1 & 0xf0) !== 0) throw new ArchiveError("Unsupported XZ stream flags");
const checkId = flag1 & 0x0f;
checkSize(checkId);
const indexSize = (read32LE(bytes, footerStart + 4) + 1) * 4;
if (!Number.isSafeInteger(indexSize) || indexSize > footerStart)
throw new ArchiveError("Invalid XZ stream: backward index size is invalid");
const indexStart = footerStart - indexSize;
const records = parseIndex(bytes, indexStart, indexSize);
let blocksSize = 0;
for (const record of records) {
blocksSize += Math.ceil(record.unpaddedSize / 4) * 4;
if (!Number.isSafeInteger(blocksSize)) throw new ArchiveError("XZ stream uses sizes too large to read safely");
}
const start = indexStart - blocksSize - 12;
if (start < 0 || start + 12 > bytes.byteLength || !equalBytes(bytes.subarray(start, start + 6), XZ_MAGIC)) {
throw new ArchiveError("Invalid XZ stream: header position or magic is invalid");View on GitHub (pinned to 9690622007)
Solutions
- Re-download or restore the file and verify its checksum (e.g. sha256 against the source)
- If slicing buffers manually, verify the footer offset is exactly end-12 for the stream
- Re-compress the data from the original source if the original is damaged
- Test the file with the xz CLI (xz -t) to confirm corruption independent of this library
Example fix
// before const slice = whole.subarray(6); // misaligned await xzDecode(slice); // footer CRC mismatch // after const slice = whole.subarray(0); // keep stream-aligned offsets await xzDecode(slice);
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-screen with an external tool when available: // $ xz -t file.xz && echo ok
Type guard
null
Try / catch
try {
await xzDecode(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("footer CRC32 mismatch")) {
throw new Error("XZ footer corrupted — re-acquire the archive");
}
throw err;
} Prevention
- Verify checksums after download/transfer
- Avoid editing compressed files in place
- Test archives with xz -t before processing
When it happens
Trigger: Any single-bit or multi-byte corruption within the 12-byte footer (CRC field at footerStart+0..3, flags at +8..9, backward size at +4..7, or the CRC-covered region), or a buffer slice misaligned by a few bytes so fields are read from wrong offsets.
Common situations: Faulty downloads/transfers, disk errors, files modified after compression (e.g. by a tool that patched bytes), or manual buffer slicing with wrong offsets in multi-stream archives.
Related errors
- Invalid XZ stream: header CRC32 mismatch
- Invalid XZ stream: padding without a stream
- Invalid XZ stream: footer magic mismatch
- Invalid XZ stream: backward index size is invalid
- Invalid XZ stream: header position or magic is invalid
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/07fb5c49d52c8052.
Report an issue: GitHub.