can1357/oh-my-pi · error · ArchiveError
Unsupported XZ filter ID 0x${filter.id.toString(16)}
Error message
Unsupported XZ filter ID 0x${filter.id.toString(16)} What it means
The XZ block decoder only implements a fixed set of optional filters: Delta (3) and the BCJ family (x86=4, PowerPC=5, IA-64=6, ARM=7/8, SPARC=9, ARM64=10, RISC-V=11). It throws when a block declares a filter ID outside the implemented switch — the stream may be valid XZ but uses a filter this decoder does not support.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:407
ia64Decode(bytes, startOffset);
break;
case 7:
armDecode(bytes, startOffset);
break;
case 8:
armThumbDecode(bytes, startOffset);
break;
case 9:
sparcDecode(bytes, startOffset);
break;
case 10:
arm64Decode(bytes, startOffset);
break;
case 11:
riscvDecode(bytes, startOffset);
break;
default:
throw new ArchiveError(`Unsupported XZ filter ID 0x${filter.id.toString(16)}`);
}
}
function verifyCheck(checkId: number, output: Uint8Array, expected: Uint8Array): void {
if (checkId === 0) return;
if (checkId === 1) {
if (read32LE(expected, 0) !== crc32(output)) throw new ArchiveError("Invalid XZ stream: block CRC32 mismatch");
return;
}
if (checkId === 4) {
const actual = crc64(output);
let stored = 0n;
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");View on GitHub (pinned to 9690622007)
Solutions
- Re-compress the archive without optional BCJ/Delta filters: `xz --format=xz -z` without --x86 etc., or plain LZMA2 only
- Decode the file externally with the reference xz binary and pass uncompressed data to the library
- Check if a newer version of this library/package adds support for the filter ID and upgrade
- If the input is untrusted, treat unsupported-filter as an expected rejection and inform the user
Example fix
// before: file compressed with an unsupported BCJ filter chain // $ xz --sparc --x86 file.bin // after: compress with default settings so blocks use LZMA2 only // $ xz -z file.bin
Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
const SUPPORTED_FILTER_IDS = new Set([3, 4, 5, 6, 8, 10, 11]);
function filtersSupported(ids: number[]): boolean {
return ids.every((id) => SUPPORTED_FILTER_IDS.has(id));
} Try / catch
try {
return await decodeXz(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.startsWith('Unsupported XZ filter ID')) {
// fall back to an external, fully-featured xz implementation
const out = await $`xz -dc archive.xz`.quiet().nothrow();
if (out.exitCode === 0) return new Uint8Array(await out.arrayBuffer());
}
throw err;
} Prevention
- Prefer plain LZMA2-only compression (no --x86/--arm64 etc.) for data destined for this decoder
- Pin encoder and decoder tool versions across your pipeline
- For third-party archives, provide an external xz fallback path
- Keep this package updated when new XZ filter IDs are standardized
When it happens
Trigger: Decoding an XZ stream whose block filter list contains an ID not handled by the switch (e.g. a hypothetical future filter, or an ID misread from a corrupt header).
Common situations: Files compressed with encoder configurations this pure-TS decoder doesn't implement (exotic filter chains); streams from newer xz versions introducing filters after this code was written; corrupted block headers yielding garbage filter IDs.
Related errors
- Unsupported XZ terminal filter ID 0x${last.id.toString(16)}
- Unsupported RAR5 filter type ${type}
- ARJ member '${memberPath}' uses unsupported compression meth
- Encrypted ARJ archives are unsupported
- Multi-volume ARJ archives are unsupported
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/860e7d728c47371a.
Report an issue: GitHub.