{"record":{"id":"eafa8d2330a994a2","repo":"can1357/oh-my-pi","slug":"bzip2-block-exhausted-its-huffman-selectors","errorCode":null,"errorMessage":"Bzip2 block exhausted its Huffman selectors","messagePattern":"Bzip2 block exhausted its Huffman selectors","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/codecs/bzip2.ts","lineNumber":282,"sourceCode":"\nfunction decodeBlockData(\n\treader: BitReader,\n\tblockSizeLimit: number,\n\tusedBytes: Uint8Array,\n\tselectors: Uint8Array,\n\ttables: HuffmanTable[],\n): Uint8Array {\n\tconst mtf = new Uint8Array(usedBytes);\n\tconst block = new Uint8Array(blockSizeLimit);\n\tlet blockLength = 0;\n\tlet selectorIndex = 0;\n\tlet groupRemaining = 0;\n\tlet table: HuffmanTable | undefined;\n\n\tconst nextSymbol = (): number => {\n\t\tif (groupRemaining === 0) {\n\t\t\tif (selectorIndex >= selectors.length) {\n\t\t\t\tthrow new ArchiveError(\"Bzip2 block exhausted its Huffman selectors\");\n\t\t\t}\n\t\t\ttable = tables[selectors[selectorIndex++]!];\n\t\t\tgroupRemaining = GROUP_SIZE;\n\t\t}\n\t\tgroupRemaining--;\n\t\treturn table!.decode(reader);\n\t};\n\n\tconst append = (byte: number, count: number): void => {\n\t\tif (count < 0 || blockLength + count > blockSizeLimit) {\n\t\t\tthrow new ArchiveError(\"Bzip2 block exceeds its declared block-size level\");\n\t\t}\n\t\tblock.fill(byte, blockLength, blockLength + count);\n\t\tblockLength += count;\n\t};\n\n\tconst endSymbol = usedBytes.length + 1;\n\tlet symbol = nextSymbol();","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/codecs/bzip2.ts#L264-L300","documentation":"During bzip2 Huffman decoding, the decoder consumes 'selectors' that map groups of 50 symbols to Huffman tables. This error is thrown when the decoder needs a new selector group but selectorIndex has already run past the end of the selector list parsed from the block header. It means the compressed bitstream is inconsistent with its own header — there are more symbols to decode than the selectors can account for.","triggerScenarios":"Calling nextSymbol (via symbol/decodeBlockData) on a bzip2 block whose selector count in the header is too small for the number of RUNA/RUNB/MTF symbols actually encoded, i.e. corrupt or truncated block data, or a block that was not fully supplied to the decoder.","commonSituations":"Decoding a corrupted or partially downloaded .bz2 file; a buggy bzip2 encoder; feeding the decompressor the wrong slice of a concatenated bzip2 stream; bit-level corruption from a bad transfer.","solutions":["Verify the .bz2 archive integrity (e.g. `bzip2 -t file.bz2`) and re-obtain or re-extract the file if corrupted.","Ensure you are passing the complete block bytes to decodeBlockData — no truncation of the input Uint8Array.","Check you are not slicing a multi-stream .bz2 file at incorrect stream boundaries.","If the data comes from a network transfer, compare checksums/byte counts against the source."],"exampleFix":"// before: feeding a truncated slice\nconst chunk = bytes.subarray(0, 1000);\ndecompressBzip2(chunk);\n// after: pass the whole stream/complete block\ndecompressBzip2(bytes);","handlingStrategy":"try-catch","validationCode":"import { ArchiveError } from \"@oh-my-pi/pi-utils\";\nif (bytes.byteLength < 4 || !textStartsWith(bytes, \"BZh\")) throw new Error(\"Not a bzip2 stream\");","typeGuard":null,"tryCatchPattern":"import { ArchiveError } from \"@oh-my-pi/pi-utils\";\ntry {\n  return decompressBzip2(bytes);\n} catch (err) {\n  if (err instanceof ArchiveError) {\n    throw new Error(`Corrupt bzip2 block (selector exhaustion): re-obtain the archive`, { cause: err });\n  }\n  throw err;\n}","preventionTips":["Test .bz2 integrity (`bzip2 -t`) before processing.","Always pass the complete stream, not a partial slice.","Verify checksums on files from network sources.","Treat this error as data corruption — do not retry decoding the same bytes."],"tags":["archive","bzip2","corrupt-data"],"backgroundTag":"corrupt-archive-bitstream","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}