can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: backward index size is invalid
Error message
Invalid XZ stream: backward index size is invalid
What it means
The footer's backward-size field encodes the size of the stream index as (stored+1)*4 bytes. discoverStreams() validates this is a safe integer and that the index actually fits before the footer; a stored size that overflows or points before the stream start means the footer is corrupt or the buffer is not a real XZ stream.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:130
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");
}
if (bytes[start + 6] !== flag0 || bytes[start + 7] !== flag1)
throw new ArchiveError("Invalid XZ stream: header and footer flags differ");
if (crc32(bytes.subarray(start + 6, start + 8)) !== read32LE(bytes, start + 8))
throw new ArchiveError("Invalid XZ stream: header CRC32 mismatch");
streams.unshift({ start, indexStart, footerStart, checkId, records });
end = start;
void padding;View on GitHub (pinned to 9690622007)
Solutions
- Verify the file integrity (xz -t or checksum) and re-acquire it if corrupt
- Re-compress the data to regenerate a consistent footer/index
- If slicing buffers, confirm the footer offset is exactly end-12 for the stream
- Reject untrusted archives up front if you know they come from an unreliable source
Example fix
// before const slice = whole.subarray(whole.byteLength - 10); // shifts footer fields await xzDecode(slice); // bogus backward size // after const slice = whole; // parse full streams, library locates the footer itself await xzDecode(slice);
Defensive patterns
Strategy: validation
Validate before calling
if (bytes.byteLength % 4 !== 0 || bytes.byteLength < 24) throw new Error("not plausibly an xz buffer"); Type guard
null
Try / catch
try {
await xzDecode(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("backward index size")) {
throw new Error("XZ index/footer inconsistent — archive is corrupt or malformed");
}
throw err;
} Prevention
- Only decode archives from trusted pipelines
- Pass full buffers so the library computes offsets itself
- Re-compress instead of patching compressed bytes
When it happens
Trigger: A backward-size field (footerStart+4..7) corrupted to an implausible value, a misaligned buffer slice so garbage is read as the size, or a deliberately malformed file whose declared index is larger than the preceding bytes.
Common situations: Corrupted downloads, fuzzed/malformed archives, or hand-assembled XZ streams with an incorrect index size encoding.
Related errors
- Invalid XZ stream: padding without a stream
- Invalid XZ Delta filter properties
- Invalid XZ BCJ filter 0x${filter.id.toString(16)} properties
- Invalid XZ stream: footer magic mismatch
- Invalid XZ stream: footer CRC32 mismatch
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/329bf39c06d88ade.
Report an issue: GitHub.