{"record":{"id":"2467065e8061f38f","repo":"can1357/oh-my-pi","slug":"invalid-xz-stream-block-crc32-mismatch","errorCode":null,"errorMessage":"Invalid XZ stream: block CRC32 mismatch","messagePattern":"Invalid XZ stream: block CRC32 mismatch","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/xz.ts","lineNumber":414,"sourceCode":"\t\t\tbreak;\n\t\tcase 9:\n\t\t\tsparcDecode(bytes, startOffset);\n\t\t\tbreak;\n\t\tcase 10:\n\t\t\tarm64Decode(bytes, startOffset);\n\t\t\tbreak;\n\t\tcase 11:\n\t\t\triscvDecode(bytes, startOffset);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new ArchiveError(`Unsupported XZ filter ID 0x${filter.id.toString(16)}`);\n\t}\n}\n\nfunction verifyCheck(checkId: number, output: Uint8Array, expected: Uint8Array): void {\n\tif (checkId === 0) return;\n\tif (checkId === 1) {\n\t\tif (read32LE(expected, 0) !== crc32(output)) throw new ArchiveError(\"Invalid XZ stream: block CRC32 mismatch\");\n\t\treturn;\n\t}\n\tif (checkId === 4) {\n\t\tconst actual = crc64(output);\n\t\tlet stored = 0n;\n\t\tfor (let index = 0; index < 8; index++) stored |= BigInt(expected[index]!) << BigInt(index * 8);\n\t\tif (actual !== stored) throw new ArchiveError(\"Invalid XZ stream: block CRC64 mismatch\");\n\t\treturn;\n\t}\n\tconst actual = new Uint8Array(new Bun.CryptoHasher(\"sha256\").update(output).digest());\n\tif (!equalBytes(actual, expected)) throw new ArchiveError(\"Invalid XZ stream: block SHA-256 mismatch\");\n}\n\nasync function decodeBlock(bytes: Uint8Array, offset: number, record: XzRecord, checkId: number): Promise<Uint8Array> {\n\tif (offset >= bytes.byteLength || bytes[offset] === 0)\n\t\tthrow new ArchiveError(\"Invalid XZ stream: missing block header\");\n\tconst headerSize = (bytes[offset]! + 1) * 4;\n\tif (offset + headerSize > bytes.byteLength || headerSize < 8)","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/xz.ts#L396-L432","documentation":"XZ blocks store an integrity check selected at stream level; check ID 1 is CRC32. After decoding a block, the library recomputes CRC32 over the uncompressed output and compares it to the 4 bytes stored in the block. A mismatch means the decoded data differs from what the encoder hashed — the stream is corrupt or was modified.","triggerScenarios":"Decompressing an XZ stream whose stream-flags declare check type CRC32 (check ID 1) and a block's stored CRC32 does not match the CRC32 of the block's decoded output.","commonSituations":"Truncated or partially downloaded .xz files; disk corruption; a stream edited after compression; decompressor bugs producing wrong output (rare).","solutions":["Re-obtain the archive from its source — this error means the data is damaged, not that decoding options are wrong","Verify externally with `xz -t` to confirm corruption independent of this library","Check for incomplete downloads (size mismatch, interrupted transfer) and retry the transfer","If corruption recurs from the same producer, re-compress and re-verify the data at the source"],"exampleFix":"// before: retrying the same corrupt bytes in a loop\nwhile (tries < 3) decodeXz(sameCorruptBuffer);\n// after: fetch a fresh copy once integrity fails\ncatch (e) { if (String(e.message).includes('CRC32 mismatch')) return downloadFreshArchive(); }","handlingStrategy":"try-catch","validationCode":"// Verify archive integrity before decode\nconst t = await $`xz -t archive.xz`.quiet().nothrow();\nif (t.exitCode !== 0) throw new Error('archive.xz failed integrity check');","typeGuard":"null","tryCatchPattern":"try {\n  return await decodeXz(bytes);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes('CRC32 mismatch')) {\n    throw new Error('XZ block data is corrupt (CRC32); re-obtain the archive');\n  }\n  throw err;\n}","preventionTips":["Compare file size/checksum against the source before decoding","Retry downloads on unstable networks and verify after transfer","Never mutate decompressed bytes and expect checks to pass — the check is over decoder output only","Log the archive's origin so corrupt sources can be identified and fixed"],"tags":["xz","archive","crc","integrity","corrupt-input"],"backgroundTag":"checksum-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}