can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: footer magic mismatch
Error message
Invalid XZ stream: footer magic mismatch
What it means
Every XZ stream ends with a 12-byte footer whose last two bytes must be the magic 'YZ' (0x59 0x5A). discoverStreams() checks these bytes after locating the footer; if they differ, the bytes at that position are not an XZ stream footer, so the buffer is not a valid (or is a corrupted) XZ stream.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:120
return records;
}
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;View on GitHub (pinned to 9690622007)
Solutions
- Confirm the input is actually XZ format (check for magic fd 37 7a 58 5a 00 at a stream start)
- Re-acquire the file and verify its checksum to rule out corruption
- If the data is raw LZMA or another format, use the matching codec instead of xz
- If handling concatenated streams, do not insert non-zero filler between them
Example fix
// before await xzDecode(gzipBytes); // wrong format // after import * as gzip from "./gzip"; await gzip.decode(gzipBytes); // use the right codec per format
Defensive patterns
Strategy: validation
Validate before calling
function hasXzMagic(bytes: Uint8Array): boolean {
return bytes.byteLength >= 6
&& bytes[0] === 0xfd && bytes[1] === 0x37 && bytes[2] === 0x7a
&& bytes[3] === 0x58 && bytes[4] === 0x5a && bytes[5] === 0x00;
} Type guard
null
Try / catch
try {
await xzDecode(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("footer magic mismatch")) {
throw new Error("Input is not a valid XZ stream — check file format");
}
throw err;
} Prevention
- Detect the actual format (xz vs gzip vs zip) before choosing a codec
- Never trust file extensions; sniff magic bytes
- Re-verify files after any manual byte manipulation
When it happens
Trigger: Feeding a non-XZ archive (gzip, zip, tar, raw LZMA) to the xz decoder; a footer corrupted by a bad transfer or write; an off-by-N slice that shifts the footer position so the magic bytes land elsewhere.
Common situations: Opening a file with the wrong extension, hand-editing or post-processing an .xz file, concatenating streams with junk between them, or byte-level corruption from a faulty disk/transfer.
Related errors
- Invalid XZ stream: header position or magic is invalid
- Invalid XZ stream: padding without a stream
- Invalid XZ stream: footer CRC32 mismatch
- Invalid XZ stream: backward index size is invalid
- Invalid XZ stream: header and footer flags differ
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ba50732590e349e7.
Report an issue: GitHub.