can1357/oh-my-pi · error · ArchiveError

Invalid XZ Delta filter properties

Error message

Invalid XZ Delta filter properties

What it means

This ArchiveError is thrown while applying the filters of an XZ block during decompression. Filter ID 3 is the Delta filter; per the XZ spec its properties must be exactly one byte (the distance minus 1). The library throws when the Delta filter's properties field has any other byte length, meaning the stream's filter properties are malformed.

Source

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

		} else {
			const register = instruction >>> 27;
			if (((instruction - 0x3117) << 18) >>> 0 >= (register & 0x1d)) {
				index += 2;
				continue;
			}
			const address = (read32BE(bytes, index + 4) - startOffset - index) >>> 0;
			instruction2 = ((instruction >>> 12) | (address << 20)) >>> 0;
			instruction = (0x17 | (register << 7) | ((address + 0x800) & 0xfffff000)) >>> 0;
		}
		write32LE(bytes, index, instruction);
		write32LE(bytes, index + 4, instruction2);
		index += 6;
	}
}

function applyFilter(bytes: Uint8Array, filter: XzFilter): void {
	if (filter.id === 3) {
		if (filter.properties.byteLength !== 1) throw new ArchiveError("Invalid XZ Delta filter properties");
		deltaDecode(bytes, filter.properties[0]! + 1);
		return;
	}
	if (filter.properties.byteLength !== 0 && filter.properties.byteLength !== 4)
		throw new ArchiveError(`Invalid XZ BCJ filter 0x${filter.id.toString(16)} properties`);
	const startOffset = filter.properties.byteLength === 4 ? read32LE(filter.properties, 0) : 0;
	const alignment = filter.id === 6 ? 16 : filter.id === 8 || filter.id === 11 ? 2 : filter.id === 4 ? 1 : 4;
	if ((startOffset & (alignment - 1)) !== 0)
		throw new ArchiveError(`Invalid XZ BCJ filter 0x${filter.id.toString(16)} start offset`);
	switch (filter.id) {
		case 4:
			x86Decode(bytes, startOffset);
			break;
		case 5:
			powerPcDecode(bytes, startOffset);
			break;
		case 6:
			ia64Decode(bytes, startOffset);

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the source file is a valid XZ archive (test with `xz -t file.xz` or an equivalent tool) and re-obtain it if corrupt
  2. Check for truncation: compare file size against the expected size or re-download/re-extract the archive
  3. Confirm the producing tool is a spec-compliant XZ encoder; re-compress with standard xz if it was generated in-house
  4. If the input is untrusted, treat this as expected rejection and surface a clear user-facing 'corrupt archive' message

Example fix

// before: properties encoded with wrong length
const filter = { id: 3, properties: new Uint8Array([4, 0]) };
// after: Delta filter must carry exactly 1 property byte (distance - 1)
const filter = { id: 3, properties: new Uint8Array([3]) }; // distance = 4
Defensive patterns

Strategy: validation

Validate before calling

// Inspect block filter properties before decode, or validate the archive externally first
import { $ } from 'bun';
const t = await $`xz -t archive.xz`.quiet().nothrow();
if (t.exitCode !== 0) throw new Error('archive.xz is not a valid XZ stream');

Type guard

function isDeltaFilter(f: { id: number; properties: Uint8Array }): boolean {
  return f.id !== 3 || f.properties.byteLength === 1;
}

Try / catch

import { ArchiveError } from '@oh-my-pi/pi-utils/ar/codecs';
try {
  await decodeXz(bytes);
} catch (err) {
  if (err instanceof ArchiveError && err.message.startsWith('Invalid XZ Delta filter')) {
    throw new Error('Archive is corrupt: malformed Delta filter properties');
  }
  throw err;
}

Prevention

When it happens

Trigger: Decompressing an XZ stream whose block header declares a Delta filter (id 3) with a properties blob that is 0 bytes or more than 1 byte — i.e. the encoded properties size byte in the block header disagrees with the XZ spec.

Common situations: Corrupt or truncated archive files; hand-crafted or fuzzed XZ input; files produced by non-conformant compressors; byte-level corruption from a bad transfer or storage medium.

Related errors


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