can1357/oh-my-pi · error · ArchiveError

Unsupported XZ stream flags

Error message

Unsupported XZ stream flags

What it means

XZ stream flags occupy two bytes in the footer: the first must be 0x00 (reserved, must be zero) and the high nibble of the second must be 0x00 (reserved). discoverStreams() rejects any footer with reserved bits set, since such a stream does not conform to the XZ specification and its meaning is undefined.

Source

Thrown at packages/utils/src/ar/codecs/xz.ts:125

		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");
		}
		if (bytes[start + 6] !== flag0 || bytes[start + 7] !== flag1)
			throw new ArchiveError("Invalid XZ stream: header and footer flags differ");

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-compress with a standard tool (xz/zstd-compatible xz encoder) to regenerate a conformant footer
  2. Verify the file with xz -t to see if the file itself is invalid
  3. Re-download/restore the file if corruption is suspected
  4. If you build XZ streams programmatically, write 0x00 for flag0 and keep flag1's high nibble zero

Example fix

// before
footer[8] = 0x01; // reserved flag bit set
// after
footer[8] = 0x00; // spec: reserved byte must be 0
footer[9] &= 0x0f; // keep only check ID in low nibble
Defensive patterns

Strategy: try-catch

Validate before calling

// The library surfaces this as a non-conformant stream; nothing to pre-check
// beyond ensuring the file comes from a standard xz encoder.

Type guard

null

Try / catch

try {
  await xzDecode(bytes);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes("Unsupported XZ stream flags")) {
    throw new Error("Archive produced by a non-conformant XZ encoder — re-compress with standard xz");
  }
  throw err;
}

Prevention

When it happens

Trigger: A footer whose flag byte at footerStart+8 is non-zero or whose flag byte at footerStart+9 has any of the upper 4 bits set — produced by a non-conformant compressor, a corrupted footer, or misaligned parsing reading wrong bytes as flags.

Common situations: Archives produced by broken or experimental XZ encoders, corruption during transfer/storage, or a hand-built XZ stream with wrong flag bytes.

Related errors


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