can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: non-zero block header padding
Error message
Invalid XZ stream: non-zero block header padding
What it means
After parsing the filters, every remaining byte of a block header up to its CRC32 must be zero padding per the XZ spec. A non-zero byte means the header is malformed, so the decoder rejects the stream. This is a strict conformance check on header padding.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:452
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");
if (declaredCompressed !== undefined && declaredCompressed !== compressedSize)
throw new ArchiveError("Invalid XZ stream: block compressed size mismatch");
if (declaredUncompressed !== undefined && declaredUncompressed !== record.uncompressedSize)
throw new ArchiveError("Invalid XZ stream: block uncompressed size mismatch");
const compressedStart = offset + headerSize;
const compressedEnd = compressedStart + compressedSize;
const paddingSize = (4 - ((headerSize + compressedSize) & 3)) & 3;
const checkStart = compressedEnd + paddingSize;
if (checkStart + integritySize > bytes.byteLength) throw new ArchiveError("Invalid XZ stream: truncated block data");
const last = filters[filters.length - 1]!;
if (last.id !== 0x21 || last.properties.byteLength !== 1)
throw new ArchiveError(`Unsupported XZ terminal filter ID 0x${last.id.toString(16)} (LZMA2 required)`);
let output = await lzma2Decompress(
last.properties[0]!,View on GitHub (pinned to 9690622007)
Solutions
- Re-download/restore the file and validate with `xz -t` before decompressing.
- Re-encode the archive with the standard xz tool if it was produced by custom code.
- Verify you are not accidentally splicing or rewriting bytes of the archive in your pipeline.
- Reject untrusted archives that fail validation instead of attempting repair.
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'); Try / catch
try {
return await xzDecompress(bytes, maxOutput);
} catch (err) {
if (err instanceof ArchiveError) throw new Error(`Corrupt XZ archive: ${err.message}`, { cause: err });
throw err;
} Prevention
- Do not modify archive bytes between creation and decompression.
- Re-encode with the stock xz tool if a custom encoder produced the file.
- Checksum archives before use in automated pipelines.
- Quarantine archives that fail validation instead of retrying.
When it happens
Trigger: xzDecompress parses a block header whose filter list ends before the header size boundary and at least one padding byte is non-zero.
Common situations: Hand-crafted or tool-mangled XZ headers, corruption from a bad editor or transfer that overwrote header bytes, or output of a non-conforming custom encoder.
Related errors
- Unsupported XZ block flags
- 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/286c0778d243790f.
Report an issue: GitHub.