{"record":{"id":"613a78f6034b9ce1","repo":"can1357/oh-my-pi","slug":"invalid-cab-archive-lzx-code-length-run-exceeds-i","errorCode":null,"errorMessage":"Invalid CAB archive: LZX code-length run exceeds its tree","messagePattern":"Invalid CAB archive: LZX code-length run exceeds its tree","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/lzx.ts","lineNumber":127,"sourceCode":"\t\t\tconst relative = code - this.#firstCodes[length]!;\n\t\t\tif (relative >= 0 && relative < this.#counts[length]!) {\n\t\t\t\treturn this.#symbols[this.#firstSymbols[length]! + relative]!;\n\t\t\t}\n\t\t}\n\t\tthrow new ArchiveError(\"Invalid CAB archive: invalid LZX Huffman symbol\");\n\t}\n}\n\nfunction readCodeLengths(reader: LzxBitReader, lengths: Uint8Array, first: number, last: number): void {\n\tconst pretreeLengths = new Uint8Array(20);\n\tfor (let index = 0; index < pretreeLengths.byteLength; index++) pretreeLengths[index] = reader.readBits(4);\n\tconst pretree = new LzxHuffmanTable(pretreeLengths);\n\tlet index = first;\n\twhile (index < last) {\n\t\tconst symbol = pretree.decode(reader);\n\t\tif (symbol === 17 || symbol === 18) {\n\t\t\tconst run = reader.readBits(symbol === 17 ? 4 : 5) + (symbol === 17 ? 4 : 20);\n\t\t\tif (index + run > last) throw new ArchiveError(\"Invalid CAB archive: LZX code-length run exceeds its tree\");\n\t\t\tlengths.fill(0, index, index + run);\n\t\t\tindex += run;\n\t\t\tcontinue;\n\t\t}\n\t\tif (symbol === 19) {\n\t\t\tconst run = reader.readBits(1) + 4;\n\t\t\tif (index + run > last) throw new ArchiveError(\"Invalid CAB archive: LZX code-length run exceeds its tree\");\n\t\t\tconst delta = pretree.decode(reader);\n\t\t\tconst length = (lengths[index]! - delta + 17) % 17;\n\t\t\tlengths.fill(length, index, index + run);\n\t\t\tindex += run;\n\t\t\tcontinue;\n\t\t}\n\t\tlengths[index] = (lengths[index]! - symbol + 17) % 17;\n\t\tindex++;\n\t}\n}\n","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/lzx.ts#L109-L145","documentation":"Thrown by readCodeLengths when a pretree symbol 17 or 18 (zero-run of length 4-19 or 20-51) would extend past the last tree index being defined. The run would write outside the tree's declared symbol range, so the block header is malformed.","triggerScenarios":"Decoding a Verbatim (type 1) or Aligned (type 2) LZX block where an encoded zero-run near the end of the main/length/aligned tree description claims more trailing zeros than remain between first and last.","commonSituations":"Corrupted CAB archives, compressors emitting run lengths that overrun the tree size, bit desync causing a normal symbol to be misread as a run symbol.","solutions":["Verify CAB integrity and re-obtain the archive.","Recompress with a standard tool so code-length runs fit the tree bounds.","Check the block header bit position; earlier desync turns ordinary symbols into spurious run codes."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  decoder.decompressFrame(bytes, size)\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes('code-length run exceeds')) {\n    throw new Error('CAB archive corrupt: malformed block header')\n  }\n  throw err\n}","preventionTips":["Validate archive integrity before decoding","Do not attempt partial resync after bitstream errors — restart the folder decode","Prefer archives produced by standard tools (makecab/cabarc/7-Zip)"],"tags":["archive","cab","lzx","huffman","corruption"],"backgroundTag":"corrupt-archive-huffman-tree","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}