can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: non-canonical variable-length integer
Error message
Invalid XZ stream: non-canonical variable-length integer
What it means
XZ varints must be canonically encoded: continuation padding bytes after the final (non-continuation) byte must be zero. A zero data byte in a non-final position means either non-canonical encoding (rejected by the spec) or corrupt data.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:47
function equalBytes(left: Uint8Array, right: Uint8Array): boolean {
if (left.byteLength !== right.byteLength) return false;
for (let index = 0; index < left.byteLength; index++) if (left[index] !== right[index]) return false;
return true;
}
interface Cursor {
bytes: Uint8Array;
pos: number;
limit: number;
}
function readVarInt(cursor: Cursor): number {
let value = 0;
for (let index = 0; index < 9; index++) {
if (cursor.pos >= cursor.limit) throw new ArchiveError("Invalid XZ stream: truncated variable-length integer");
const byte = cursor.bytes[cursor.pos++]!;
if (index > 0 && byte === 0) throw new ArchiveError("Invalid XZ stream: non-canonical variable-length integer");
value += (byte & 0x7f) * 2 ** (index * 7);
if (!Number.isSafeInteger(value)) throw new ArchiveError("XZ stream uses sizes too large to read safely");
if ((byte & 0x80) === 0) return value;
}
throw new ArchiveError("Invalid XZ stream: variable-length integer is too long");
}
interface XzRecord {
unpaddedSize: number;
uncompressedSize: number;
}
interface XzStream {
start: number;
indexStart: number;
footerStart: number;
checkId: number;
records: XzRecord[];View on GitHub (pinned to 9690622007)
Solutions
- Re-download or re-compress the .xz file with a standard tool (xz, liblzma).
- Locate corruption with `xz -t file.xz` outside the library.
- Treat as invalid input; the library intentionally rejects non-canonical encodings per the XZ format spec.
Defensive patterns
Strategy: validation
Validate before calling
// reject obviously corrupt varint prefixes before parsing
function varintRegionLooksSane(bytes, offset, limit) {
return offset >= 0 && offset <= limit && limit <= bytes.byteLength;
} Try / catch
try {
const idx = parseIndex(bytes, indexOffset);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("non-canonical")) {
throw new Error("XZ stream contains non-canonical/corrupt size fields");
}
throw err;
} Prevention
- Verify archive integrity with `xz -t` or CRC before parsing
- Only parse .xz files produced by standard compressors
- Treat non-canonical encodings as corruption, not a recoverable condition
When it happens
Trigger: readVarInt reads a byte === 0 at index > 0 — i.e. a 0x00 where a meaningful payload or 0x80-continuation byte was required.
Common situations: Corrupted .xz stream, hand-crafted or fuzzed varints, zero-fill overwriting part of an index/block header.
Related errors
- Invalid XZ stream: truncated variable-length integer
- Unsupported XZ block flags
- Invalid XZ stream: truncated filter properties
- Invalid XZ stream: non-zero block header padding
- 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/f1203236fa437925.
Report an issue: GitHub.