{"record":{"id":"3c07ec3de9f47bb3","repo":"can1357/oh-my-pi","slug":"invalid-xz-stream-truncated-stream-framing","errorCode":null,"errorMessage":"Invalid XZ stream: truncated stream framing","messagePattern":"Invalid XZ stream: truncated stream framing","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/xz.ts","lineNumber":117,"sourceCode":"\t}\n\twhile (cursor.pos < cursor.limit)\n\t\tif (bytes[cursor.pos++] !== 0) throw new ArchiveError(\"Invalid XZ stream: non-zero index padding\");\n\treturn records;\n}\n\nfunction discoverStreams(bytes: Uint8Array): XzStream[] {\n\tif (bytes.byteLength === 0 || (bytes.byteLength & 3) !== 0)\n\t\tthrow new ArchiveError(\"Invalid XZ stream: size is not a multiple of four bytes\");\n\tconst streams: XzStream[] = [];\n\tlet end = bytes.byteLength;\n\twhile (end > 0) {\n\t\tlet padding = 0;\n\t\twhile (end >= 4 && bytes[end - 1] === 0 && bytes[end - 2] === 0 && bytes[end - 3] === 0 && bytes[end - 4] === 0) {\n\t\t\tend -= 4;\n\t\t\tpadding += 4;\n\t\t}\n\t\tif (end === 0) throw new ArchiveError(\"Invalid XZ stream: padding without a stream\");\n\t\tif (end < 24) throw new ArchiveError(\"Invalid XZ stream: truncated stream framing\");\n\t\tconst footerStart = end - 12;\n\t\tif (bytes[footerStart + 10] !== 0x59 || bytes[footerStart + 11] !== 0x5a)\n\t\t\tthrow new ArchiveError(\"Invalid XZ stream: footer magic mismatch\");\n\t\tif (crc32(bytes.subarray(footerStart + 4, footerStart + 10)) !== read32LE(bytes, footerStart))\n\t\t\tthrow new ArchiveError(\"Invalid XZ stream: footer CRC32 mismatch\");\n\t\tconst flag0 = bytes[footerStart + 8]!;\n\t\tconst flag1 = bytes[footerStart + 9]!;\n\t\tif (flag0 !== 0 || (flag1 & 0xf0) !== 0) throw new ArchiveError(\"Unsupported XZ stream flags\");\n\t\tconst checkId = flag1 & 0x0f;\n\t\tcheckSize(checkId);\n\t\tconst indexSize = (read32LE(bytes, footerStart + 4) + 1) * 4;\n\t\tif (!Number.isSafeInteger(indexSize) || indexSize > footerStart)\n\t\t\tthrow new ArchiveError(\"Invalid XZ stream: backward index size is invalid\");\n\t\tconst indexStart = footerStart - indexSize;\n\t\tconst records = parseIndex(bytes, indexStart, indexSize);\n\t\tlet blocksSize = 0;\n\t\tfor (const record of records) {\n\t\t\tblocksSize += Math.ceil(record.unpaddedSize / 4) * 4;","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/xz.ts#L99-L135","documentation":"After stripping trailing zero padding, discoverStreams() requires at least 24 bytes remaining — the minimum for a 12-byte stream header plus a 12-byte stream footer. A shorter remainder means the stream framing is cut off mid-structure, so the library refuses to parse it rather than produce garbage.","triggerScenarios":"Passing a buffer whose non-padding tail is shorter than 24 bytes — e.g. a truncated .xz download, a partial read, or a slice that ends mid-footer. Also happens when concatenation handling drops the leading stream's header.","commonSituations":"Interrupted file transfers, HTTP range requests that fetched only part of the file, copying a file while it was still being written, or incorrectly slicing multi-stream xz buffers.","solutions":["Verify file size matches the expected .xz size and re-download/re-copy if truncated","Check that the source transfer completed (checksum the file)","If slicing a buffer manually, include at least the full 24-byte header+footer framing","Only strip padding you know belongs between streams; keep whole streams intact"],"exampleFix":"// before\nconst bytes = buf.subarray(0, 20); // truncated\nawait xzDecode(bytes);\n// after\nif (buf.byteLength < 24) throw new Error(\"xz buffer too small (<24 bytes)\");\nconst bytes = buf;\nawait xzDecode(bytes);","handlingStrategy":"validation","validationCode":"if (bytes.byteLength < 24) throw new Error(`xz input too small: ${bytes.byteLength} bytes (min 24)`);","typeGuard":"null","tryCatchPattern":"try {\n  await xzDecode(bytes);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"truncated stream framing\")) {\n    throw new Error(\"XZ file is truncated or incomplete\");\n  }\n  throw err;\n}","preventionTips":["Verify downloaded file sizes against expected sizes","Use checksums to confirm complete transfers","Avoid reading files while a producer is still writing them"],"tags":["xz","archive","truncated-input"],"backgroundTag":"invalid-archive-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}