can1357/oh-my-pi · error · ArchiveError
Invalid XZ stream: truncated integer
Error message
Invalid XZ stream: truncated integer
What it means
read32LE reads a little-endian uint32 from a byte buffer and throws when the 4-byte range [offset, offset+4) falls outside the buffer. The XZ stream being parsed is too short at the expected field location.
Source
Thrown at packages/utils/src/ar/codecs/xz.ts:8
import { crc32, crc64 } from "../checksums";
import { ArchiveError } from "../error";
import { lzma2Decompress } from "./lzma";
const XZ_MAGIC = Uint8Array.of(0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00);
function read32LE(bytes: Uint8Array, offset: number): number {
if (offset < 0 || offset + 4 > bytes.byteLength) throw new ArchiveError("Invalid XZ stream: truncated integer");
return (bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24)) >>> 0;
}
function write32LE(bytes: Uint8Array, offset: number, value: number): void {
bytes[offset] = value & 0xff;
bytes[offset + 1] = (value >>> 8) & 0xff;
bytes[offset + 2] = (value >>> 16) & 0xff;
bytes[offset + 3] = value >>> 24;
}
function read32BE(bytes: Uint8Array, offset: number): number {
return ((bytes[offset]! << 24) | (bytes[offset + 1]! << 16) | (bytes[offset + 2]! << 8) | bytes[offset + 3]!) >>> 0;
}
function write32BE(bytes: Uint8Array, offset: number, value: number): void {
bytes[offset] = value >>> 24;
bytes[offset + 1] = (value >>> 16) & 0xff;
bytes[offset + 2] = (value >>> 8) & 0xff;View on GitHub (pinned to 9690622007)
Solutions
- Check the file size — a valid .xz stream is at least 12 bytes (6-byte magic + 2-byte header + footer).
- Re-download the file; compare byte size with the source.
- Ensure you pass the complete stream/padded-size region to the parser, not a truncated slice.
Example fix
// before
const footer = bytes.subarray(bytes.length - 6); // may be < 6 bytes if truncated
parseFooter(footer);
// after
if (bytes.byteLength < 12) throw new Error("XZ stream too short");
const footer = bytes.subarray(bytes.length - 6); Defensive patterns
Strategy: validation
Validate before calling
if (!bytes || bytes.byteLength < 12) {
throw new Error("Input is not a complete XZ stream (minimum 12 bytes)");
}
if (!XZ_MAGIC.every((b, i) => bytes[i] === b)) {
throw new Error("Input does not start with XZ magic");
} Type guard
function isCompleteXzStream(bytes) {
return bytes instanceof Uint8Array && bytes.byteLength >= 12;
} Try / catch
try {
const streams = discoverStreams(bytes);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("truncated integer")) {
throw new Error("XZ input is truncated — re-download the file");
}
throw err;
} Prevention
- Check file size >= 12 bytes and XZ magic bytes before parsing
- Verify completed downloads (size + CRC) before extraction
- Pass the full buffer, never a mid-stream slice, to stream discovery
When it happens
Trigger: parseIndex, discoverStreams, or indexSize reads a 32-bit field (stream footer/header, CRC, index field) whose offset is beyond the supplied bytes — e.g. a stream shorter than 12 bytes or an index past EOF.
Common situations: Truncated .xz download, concatenating/parsing a byte slice that cuts a stream mid-structure, padding-only input, or passing a partial buffer instead of the full stream.
Related errors
- Invalid XZ stream: truncated variable-length integer
- Invalid ARJ archive: truncated data
- Invalid XZ stream: non-canonical variable-length integer
- Invalid XZ stream: padding without a stream
- Invalid XZ stream: truncated stream framing
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/9c545d01a4d36ca6.
Report an issue: GitHub.