{"record":{"id":"9c545d01a4d36ca6","repo":"can1357/oh-my-pi","slug":"invalid-xz-stream-truncated-integer","errorCode":null,"errorMessage":"Invalid XZ stream: truncated integer","messagePattern":"Invalid XZ stream: truncated integer","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/xz.ts","lineNumber":8,"sourceCode":"import { crc32, crc64 } from \"../checksums\";\nimport { ArchiveError } from \"../error\";\nimport { lzma2Decompress } from \"./lzma\";\n\nconst XZ_MAGIC = Uint8Array.of(0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00);\n\nfunction read32LE(bytes: Uint8Array, offset: number): number {\n\tif (offset < 0 || offset + 4 > bytes.byteLength) throw new ArchiveError(\"Invalid XZ stream: truncated integer\");\n\treturn (bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24)) >>> 0;\n}\n\nfunction write32LE(bytes: Uint8Array, offset: number, value: number): void {\n\tbytes[offset] = value & 0xff;\n\tbytes[offset + 1] = (value >>> 8) & 0xff;\n\tbytes[offset + 2] = (value >>> 16) & 0xff;\n\tbytes[offset + 3] = value >>> 24;\n}\n\nfunction read32BE(bytes: Uint8Array, offset: number): number {\n\treturn ((bytes[offset]! << 24) | (bytes[offset + 1]! << 16) | (bytes[offset + 2]! << 8) | bytes[offset + 3]!) >>> 0;\n}\n\nfunction write32BE(bytes: Uint8Array, offset: number, value: number): void {\n\tbytes[offset] = value >>> 24;\n\tbytes[offset + 1] = (value >>> 16) & 0xff;\n\tbytes[offset + 2] = (value >>> 8) & 0xff;","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/xz.ts#L1-L26","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst footer = bytes.subarray(bytes.length - 6); // may be < 6 bytes if truncated\nparseFooter(footer);\n// after\nif (bytes.byteLength < 12) throw new Error(\"XZ stream too short\");\nconst footer = bytes.subarray(bytes.length - 6);","handlingStrategy":"validation","validationCode":"if (!bytes || bytes.byteLength < 12) {\n  throw new Error(\"Input is not a complete XZ stream (minimum 12 bytes)\");\n}\nif (!XZ_MAGIC.every((b, i) => bytes[i] === b)) {\n  throw new Error(\"Input does not start with XZ magic\");\n}","typeGuard":"function isCompleteXzStream(bytes) {\n  return bytes instanceof Uint8Array && bytes.byteLength >= 12;\n}","tryCatchPattern":"try {\n  const streams = discoverStreams(bytes);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"truncated integer\")) {\n    throw new Error(\"XZ input is truncated — re-download the file\");\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["archive","xz","truncation"],"backgroundTag":"truncated-archive-stream","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}