can1357/oh-my-pi · error · ArchiveError
Unsupported XZ block flags
Error message
Unsupported XZ block flags
What it means
The XZ block header's flags byte has bits 2-5 (0x3c) set, which are reserved by the XZ format and must be zero. This decoder strictly validates the format and rejects the block rather than guessing. It is thrown while parsing a block header inside xzDecompress/decodeBlock (packages/utils/src/ar/codecs/xz.ts:438).
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:438
for (let index = 0; index < 8; index++) stored |= BigInt(expected[index]!) << BigInt(index * 8);
if (actual !== stored) throw new ArchiveError("Invalid XZ stream: block CRC64 mismatch");
return;
}
const actual = new Uint8Array(new Bun.CryptoHasher("sha256").update(output).digest());
if (!equalBytes(actual, expected)) throw new ArchiveError("Invalid XZ stream: block SHA-256 mismatch");
}
async function decodeBlock(bytes: Uint8Array, offset: number, record: XzRecord, checkId: number): Promise<Uint8Array> {
if (offset >= bytes.byteLength || bytes[offset] === 0)
throw new ArchiveError("Invalid XZ stream: missing block header");
const headerSize = (bytes[offset]! + 1) * 4;
if (offset + headerSize > bytes.byteLength || headerSize < 8)
throw new ArchiveError("Invalid XZ stream: truncated block header");
if (crc32(bytes.subarray(offset, offset + headerSize - 4)) !== read32LE(bytes, offset + headerSize - 4))
throw new ArchiveError("Invalid XZ stream: block header CRC32 mismatch");
const cursor: Cursor = { bytes, pos: offset + 1, limit: offset + headerSize - 4 };
const flags = bytes[cursor.pos++]!;
if ((flags & 0x3c) !== 0) throw new ArchiveError("Unsupported XZ block flags");
const filterCount = (flags & 3) + 1;
const declaredCompressed = (flags & 0x40) !== 0 ? readVarInt(cursor) : undefined;
const declaredUncompressed = (flags & 0x80) !== 0 ? readVarInt(cursor) : undefined;
const filters: XzFilter[] = [];
for (let index = 0; index < filterCount; index++) {
const id = readVarInt(cursor);
const propertySize = readVarInt(cursor);
if (propertySize > cursor.limit - cursor.pos)
throw new ArchiveError("Invalid XZ stream: truncated filter properties");
filters.push({ id, properties: bytes.slice(cursor.pos, cursor.pos + propertySize) });
cursor.pos += propertySize;
}
while (cursor.pos < cursor.limit)
if (bytes[cursor.pos++] !== 0) throw new ArchiveError("Invalid XZ stream: non-zero block header padding");
const integritySize = checkSize(checkId);
const compressedSize = record.unpaddedSize - headerSize - integritySize;
if (!Number.isSafeInteger(compressedSize) || compressedSize <= 0)
throw new ArchiveError("Invalid XZ stream: compressed block size is invalid");View on GitHub (pinned to 9690622007)
Solutions
- Re-download or restore the .xz file and verify its checksum against the published one.
- Test the file with `xz -t file.xz` (or `xz -l`) to confirm it is valid; re-compress with `xz` if the source encoder was non-standard.
- Ensure you are passing the full XZ stream bytes, not a slice starting mid-file, to xzDecompress.
- If you need reserved-flag XZ variants, they are out of scope for this decoder; use a full-featured XZ implementation.
Example fix
// before
await xzDecompress(partiallyDownloadedBytes, maxOutput);
// after
const bytes = await Bun.file('archive.tar.xz').bytes();
await xzDecompress(bytes, maxOutput); // complete, checksum-verified file Defensive patterns
Strategy: try-catch
Validate before calling
import { isXz } from '@oh-my-pi/pi-utils/ar/codecs/xz';
if (!isXz(bytes)) throw new Error('Not an XZ stream'); Type guard
function isXzStream(bytes: Uint8Array): boolean {
const magic = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00];
return bytes.byteLength >= magic.length && magic.every((b, i) => bytes[i] === b);
} Try / catch
import { ArchiveError } from '@oh-my-pi/pi-utils/ar';
try {
const out = await xzDecompress(bytes, maxOutput);
} catch (err) {
if (err instanceof ArchiveError) {
logger.warn('XZ archive invalid, skipping', { message: err.message });
return fallbackPath();
}
throw err;
} Prevention
- Verify file checksums before decompressing untrusted or transferred archives.
- Sanity-check the XZ magic bytes before calling xzDecompress.
- Never hand-edit or post-process archive bytes.
- Probe with `xz -t` during ingestion pipelines for batch archives.
When it happens
Trigger: Calling xzDecompress (or an archive-extract API that routes to it) on bytes whose block header flags byte contains any of the reserved bits 0x3c — i.e. a corrupt, hand-edited, or non-conforming XZ file.
Common situations: Corrupted downloads (truncated then re-saved archives), files produced by buggy or experimental XZ encoders, bit-flipped bytes on damaged storage, or mistaking a similarly-named non-XZ file for an XZ stream.
Related errors
- Invalid XZ stream: non-zero block header padding
- Invalid XZ stream: non-zero block padding
- Invalid XZ stream: non-canonical variable-length integer
- Invalid XZ stream: truncated filter properties
- Invalid XZ stream: compressed block size is invalid
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/850151ad1bb33a08.
Report an issue: GitHub.