can1357/oh-my-pi · error · ArchiveError

Invalid XZ stream: block uncompressed size mismatch

Error message

Invalid XZ stream: block uncompressed size mismatch

What it means

The block header optionally declares the uncompressed size (flags bit 0x80). When present, it must equal the uncompressed size recorded in the stream index. A mismatch means the header and index contradict each other and the stream is invalid.

Source

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

	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]!,
		bytes.subarray(compressedStart, compressedEnd),
		record.uncompressedSize,
	);
	if (output.byteLength !== record.uncompressedSize)
		throw new ArchiveError("Invalid XZ stream: decoded block size mismatch");
	output = output.slice();
	for (let index = filters.length - 2; index >= 0; index--) applyFilter(output, filters[index]!);
	for (let index = compressedEnd; index < checkStart; index++)

View on GitHub (pinned to 9690622007)

Solutions

  1. Validate the file with `xz -t` and re-download or re-compress if it fails.
  2. Re-encode with the standard xz tool if a custom producer wrote mismatched sizes.
  3. Confirm your pipeline does not alter archive bytes between creation and decompression.
  4. Handle ArchiveError explicitly so invalid archives fail fast with a clear message.
Defensive patterns

Strategy: validation

Validate before calling

const ok = await $`xz -t ${path}`.quiet().nothrow();
if (ok.exitCode !== 0) throw new Error(`XZ archive failed integrity test: ${path}`);

Try / catch

try {
	return await xzDecompress(bytes, maxOutput);
} catch (err) {
	if (err instanceof ArchiveError && /uncompressed size mismatch/i.test(err.message)) {
		throw new Error('Header/index disagree on uncompressed size — archive is corrupt');
	}
	throw err;
}

Prevention

When it happens

Trigger: xzDecompress reads a block header with the uncompressed-size-present flag set whose declared value differs from record.uncompressedSize.

Common situations: Corrupted downloads, third-party or buggy XZ encoders writing inconsistent metadata, or archives modified after creation.

Related errors


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