mozilla/pdf.js · error · JpegError

invalid huffman sequence

Error message

invalid huffman sequence

What it means

Thrown by decodeHuffman() while walking a JPEG Huffman tree bit-by-bit. The loop expects each visited node to be either a number (leaf -> decoded symbol) or an object (branch -> keep traversing). When node becomes undefined (no child for the read bit), typeof falls through the switch and the error fires. This means the entropy-coded bit stream does not match any valid Huffman code path in the loaded table.

Source

Thrown at src/core/jpg.js:206

        );
      }
      // unstuff 0
    }
    bitsCount = 7;
    return bitsData >>> 7;
  }

  function decodeHuffman(tree) {
    let node = tree;
    while (true) {
      node = node[readBit()];
      switch (typeof node) {
        case "number":
          return node;
        case "object":
          continue;
      }
      throw new JpegError("invalid huffman sequence");
    }
  }

  function receive(length) {
    let n = 0;
    while (length > 0) {
      n = (n << 1) | readBit();
      length--;
    }
    return n;
  }

  function receiveAndExtend(length) {
    if (length === 1) {
      return readBit() === 1 ? 1 : -1;
    }
    const n = receive(length);
    if (n >= 1 << (length - 1)) {

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Re-extract the raw JPEG stream from the PDF and validate it with an external JPEG decoder (e.g. libjpeg, ImageMagick identify) to confirm corruption.
  2. If the stream is truncated, ensure the PDF object's /Length or stream boundaries are correct and that range-request fetching delivered all bytes.
  3. Verify the DHT (0xFFC4) markers define complete Huffman tables before the SOS (0xFFDA) scan references them.
  4. If the image is non-critical, catch JpegError and render a placeholder instead of failing the whole page render.

Example fix

// before
const jpegImg = new JpegImage();
jpegImg.parse(data);
const pixels = jpegImg.getData({ width, height });

// after — guard decode so one bad image doesn't kill page rendering
try {
  const jpegImg = new JpegImage();
  jpegImg.parse(data);
  pixels = jpegImg.getData({ width, height });
} catch (e) {
  if (e.name === 'JpegError') {
  pixels = null;
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  jpegImg.parse(data);
  pixels = jpegImg.getData({ width, height });
} catch (e) {
  if (e.name === 'JpegError') { pixels = null; }
  throw e;
}

Prevention

When it happens

Trigger: Reached during baseline/progressive JPEG scan decoding (decodeBaseline, decodeDCFirst, decodeACSuccessive, etc.) when a Huffman table (huffmanTableDC/huffmanTableAC) is malformed or the scan bit-stream is corrupted/truncated so the tree walk hits a missing branch. Also fires if the wrong table index was assigned to a component.

Common situations: Truncated JPEG data embedded in a PDF (partial stream), a corrupted DHT marker that built an incomplete tree, or an encoder that emitted bits inconsistent with the declared table. Common with PDFs produced by broken scanner/fax pipelines or with mismatched DHT/SOS component selectors.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/b95b37831906c68f. Report an issue: GitHub.