can1357/oh-my-pi · error · ArchiveError
Bzip2 block exhausted its Huffman selectors
Error message
Bzip2 block exhausted its Huffman selectors
What it means
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.
Source
Thrown at packages/utils/src/ar/codecs/bzip2.ts:282
function decodeBlockData(
reader: BitReader,
blockSizeLimit: number,
usedBytes: Uint8Array,
selectors: Uint8Array,
tables: HuffmanTable[],
): Uint8Array {
const mtf = new Uint8Array(usedBytes);
const block = new Uint8Array(blockSizeLimit);
let blockLength = 0;
let selectorIndex = 0;
let groupRemaining = 0;
let table: HuffmanTable | undefined;
const nextSymbol = (): number => {
if (groupRemaining === 0) {
if (selectorIndex >= selectors.length) {
throw new ArchiveError("Bzip2 block exhausted its Huffman selectors");
}
table = tables[selectors[selectorIndex++]!];
groupRemaining = GROUP_SIZE;
}
groupRemaining--;
return table!.decode(reader);
};
const append = (byte: number, count: number): void => {
if (count < 0 || blockLength + count > blockSizeLimit) {
throw new ArchiveError("Bzip2 block exceeds its declared block-size level");
}
block.fill(byte, blockLength, blockLength + count);
blockLength += count;
};
const endSymbol = usedBytes.length + 1;
let symbol = nextSymbol();View on GitHub (pinned to 9690622007)
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.
Example fix
// before: feeding a truncated slice const chunk = bytes.subarray(0, 1000); decompressBzip2(chunk); // after: pass the whole stream/complete block decompressBzip2(bytes);
Defensive patterns
Strategy: try-catch
Validate before calling
import { ArchiveError } from "@oh-my-pi/pi-utils";
if (bytes.byteLength < 4 || !textStartsWith(bytes, "BZh")) throw new Error("Not a bzip2 stream"); Try / catch
import { ArchiveError } from "@oh-my-pi/pi-utils";
try {
return decompressBzip2(bytes);
} catch (err) {
if (err instanceof ArchiveError) {
throw new Error(`Corrupt bzip2 block (selector exhaustion): re-obtain the archive`, { cause: err });
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Bzip2 block exceeds its declared block-size level
- Corrupt compress (.Z) dictionary code ${code}
- Corrupt compress (.Z) dictionary chain
- Invalid CAB archive: misaligned LZX byte stream
- Invalid CAB archive: invalid LZX Huffman code length
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eafa8d2330a994a2.
Report an issue: GitHub.