{"record":{"id":"a582aac7d040f822","repo":"can1357/oh-my-pi","slug":"invalid-xz-stream-blocks-do-not-align-with-index","errorCode":null,"errorMessage":"Invalid XZ stream: blocks do not align with index","messagePattern":"Invalid XZ stream: blocks do not align with index","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/xz.ts","lineNumber":515,"sourceCode":"\t\tlet totalSize = 0;\n\t\tfor (const stream of streams)\n\t\t\tfor (const record of stream.records) {\n\t\t\t\ttotalSize += record.uncompressedSize;\n\t\t\t\tif (!Number.isSafeInteger(totalSize) || totalSize > maxOutput)\n\t\t\t\t\tthrow new ArchiveError(\"XZ output exceeds its size limit\");\n\t\t\t}\n\t\tconst output = new Uint8Array(totalSize);\n\t\tlet outputPosition = 0;\n\t\tfor (const stream of streams) {\n\t\t\tlet blockPosition = stream.start + 12;\n\t\t\tfor (const record of stream.records) {\n\t\t\t\tconst block = await decodeBlock(bytes, blockPosition, record, stream.checkId);\n\t\t\t\toutput.set(block, outputPosition);\n\t\t\t\toutputPosition += block.byteLength;\n\t\t\t\tblockPosition += Math.ceil(record.unpaddedSize / 4) * 4;\n\t\t\t}\n\t\t\tif (blockPosition !== stream.indexStart)\n\t\t\t\tthrow new ArchiveError(\"Invalid XZ stream: blocks do not align with index\");\n\t\t}\n\t\treturn output;\n\t} catch (error) {\n\t\tif (error instanceof ArchiveError) throw error;\n\t\tthrow new ArchiveError(`Invalid XZ stream: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n}\n","sourceCodeStart":497,"sourceCodeEnd":523,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/xz.ts#L497-L523","documentation":"After decoding each block in an XZ stream, the library walks the block positions using index-record sizes and requires the final position to land exactly on the stream's index start. If it doesn't, the block sequence and the index disagree — the stream layout is inconsistent.","triggerScenarios":"Calling xzDecompress on bytes where block padding was altered, blocks were added/removed without regenerating the index, or the bytes are a spliced mix of two XZ streams.","commonSituations":"Archives modified or repaired by non-conformant tools; corruption in the middle of a .xz file; manually concatenated files where stream framing was broken.","solutions":["Obtain an intact copy of the archive and re-decompress","Verify with xz -t to confirm the container is broken independently of this library","If you construct XZ data programmatically, regenerate the index whenever blocks change"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { isXz } from '@oh-my-pi/pi-utils/ar/codecs/xz';\nif (!isXz(bytes)) throw new Error('not XZ');\n// integrity check out of band before parsing\n// e.g. run: Bun.spawnSync(['xz','-t','--file',path])","typeGuard":null,"tryCatchPattern":"try {\n  const out = await xzDecompress(bytes, limit);\n} catch (err) {\n  if (err instanceof ArchiveError && /blocks do not align with index/.test(err.message)) {\n    // stream layout broken: re-acquire the archive\n  } else throw err;\n}","preventionTips":["Do not modify or repair XZ files byte-wise; regenerate with xz instead","Keep streams intact when concatenating XZ files","Pre-validate archives from untrusted channels with an independent tool"],"tags":["xz","archive","corruption","index"],"backgroundTag":"xz-stream-corrupt","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}