{"record":{"id":"6b4edaf6faae3515","repo":"can1357/oh-my-pi","slug":"invalid-cab-archive-lzx-position-slot-is-out-of-r","errorCode":null,"errorMessage":"Invalid CAB archive: LZX position slot is out of range","messagePattern":"Invalid CAB archive: LZX position slot is out of range","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/lzx.ts","lineNumber":302,"sourceCode":"\t\t\tif (matchLength > count - produced || matchLength > this.#blockRemaining - produced) {\n\t\t\t\tthrow new ArchiveError(\"Invalid CAB archive: LZX match crosses a frame or block boundary\");\n\t\t\t}\n\n\t\t\tconst slot = match >>> 3;\n\t\t\tlet matchOffset: number;\n\t\t\tif (slot === 0) {\n\t\t\t\tmatchOffset = this.#r0;\n\t\t\t} else if (slot === 1) {\n\t\t\t\tmatchOffset = this.#r1;\n\t\t\t\tthis.#r1 = this.#r0;\n\t\t\t\tthis.#r0 = matchOffset;\n\t\t\t} else if (slot === 2) {\n\t\t\t\tmatchOffset = this.#r2;\n\t\t\t\tthis.#r2 = this.#r0;\n\t\t\t\tthis.#r0 = matchOffset;\n\t\t\t} else {\n\t\t\t\tif (slot >= this.#positionBase.byteLength)\n\t\t\t\t\tthrow new ArchiveError(\"Invalid CAB archive: LZX position slot is out of range\");\n\t\t\t\tconst extra = this.#extraBits[slot]!;\n\t\t\t\tmatchOffset = this.#positionBase[slot]! - 2;\n\t\t\t\tif (this.#blockType === 2 && extra >= 3) {\n\t\t\t\t\tif (extra > 3) matchOffset += reader.readBits(extra - 3) * 8;\n\t\t\t\t\tif (!this.#alignedTable) throw new ArchiveError(\"Invalid CAB archive: missing LZX aligned tree\");\n\t\t\t\t\tmatchOffset += this.#alignedTable.decode(reader);\n\t\t\t\t} else if (extra !== 0) {\n\t\t\t\t\tmatchOffset += reader.readBits(extra);\n\t\t\t\t}\n\t\t\t\tthis.#r2 = this.#r1;\n\t\t\t\tthis.#r1 = this.#r0;\n\t\t\t\tthis.#r0 = matchOffset;\n\t\t\t}\n\n\t\t\tif (matchOffset <= 0 || matchOffset > Math.min(this.#decodedSize, this.#window.byteLength)) {\n\t\t\t\tthrow new ArchiveError(\"Invalid CAB archive: LZX match offset exceeds available history\");\n\t\t\t}\n\t\t\tfor (let index = 0; index < matchLength; index++) {","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/lzx.ts#L284-L320","documentation":"The decoded match's position slot indexes beyond the precomputed positionBase/extraBits tables. Valid LZX position slots are bounded by the window size; an out-of-range slot means the Huffman-decoded symbol stream is corrupt.","triggerScenarios":"decompressFrame -> #decodeRun computes slot = match >>> 3 and slot >= positionBase.byteLength for a non-repeated-offset match.","commonSituations":"Corrupt CAB payloads or bitstream desync causing garbage Huffman symbols; archives compressed with parameters the decoder doesn't expect.","solutions":["Re-validate/re-download the CAB archive.","Confirm the window size used to initialize the decoder matches the folder's LZX window bits.","Treat as unrecoverable corruption and surface ArchiveError."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure decoder window matches folder params\nfunction windowBitsValid(windowBits) { return windowBits >= 15 && windowBits <= 23; }","typeGuard":null,"tryCatchPattern":"try {\n  const out = decompressFrame(frame);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"position slot\")) {\n    // bitstream desync or unsupported window — treat file as corrupt\n  } else throw err;\n}","preventionTips":["Initialize the decoder with the folder's actual LZX window size","Check archive integrity before decode","Fail fast rather than attempting partial recovery"],"tags":["archive","cab","lzx","corrupt-data"],"backgroundTag":"corrupt-archive-data","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}