BabylonJS/Babylon.js · error · Error

hufDecode issues

Error message

hufDecode issues

What it means

In HufDecode, when the fetched table entry has no direct literal but also has no overflow pointer (`pl.p` is falsy), the decoder has no valid way to continue interpreting the bitstream — the table lookup hit an empty/inconsistent entry — so it throws "hufDecode issues". This indicates the huf bitstream does not match the decode table built from the same file.

Source

Thrown at packages/dev/core/src/Materials/Textures/Loaders/EXR/exrLoader.compression.huf.ts:363

        c = gc.c;
        lc = gc.lc;

        while (lc >= HUF_DECBITS) {
            const index = (c >> (lc - HUF_DECBITS)) & HUF_DECMASK;
            const pl = decodingTable[index];

            if (pl.len) {
                lc -= pl.len;

                const gCode = GetCode(pl.lit, rlc, c, lc, array, offset, outBuffer, outOffset, outBufferEndOffset);
                if (gCode) {
                    c = gCode.c;
                    lc = gCode.lc;
                }
            } else {
                if (!pl.p) {
                    throw new Error("hufDecode issues");
                }

                let j;

                for (j = 0; j < pl.lit; j++) {
                    const l = HufLength(encodingTable[pl.p[j]]);

                    while (lc < l && offset.value < inOffsetEnd) {
                        gc = GetChar(c, lc, array, offset);

                        c = gc.c;
                        lc = gc.lc;
                    }

                    if (lc >= l) {
                        if (HufCode(encodingTable[pl.p[j]]) == ((c >> (lc - l)) & ((1 << l) - 1))) {
                            lc -= l;

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Replace the EXR asset with an intact copy; verify with checksum against the source.
  2. Re-export the file with a standard OpenEXR writer, ideally with zip or piz compression instead of huf.
  3. Ensure no server/proxy modifies the payload (disable transform/rewrite rules for .exr).
  4. Handle the throw at load time and fall back to a re-encoded texture.
Defensive patterns

Strategy: try-catch

Validate before calling

async function exrLooksComplete(url) {
  const res = await fetch(url, { headers: { Range: 'bytes=-8' } });
  if (!res.ok) return false;
  const tail = new Uint8Array(await res.arrayBuffer());
  return tail.length === 8; // presence of terminal offset table bytes suggests an untruncated file
}

Type guard

function isExrBuffer(data) {
  return data instanceof ArrayBuffer &&
    data.byteLength >= 8 &&
    new DataView(data).getUint32(0, true) === 20000630;
}

Try / catch

try {
  const tex = await loadExrTexture(url);
} catch (e) {
  if (e instanceof Error && (e.message === 'hufDecode issues' || e.message === 'Invalid table entry')) {
    showUserError('This EXR file is damaged and cannot be rendered.');
    useFallbackTexture();
  } else { throw e; }
}

Prevention

When it happens

Trigger: Bitstream of a huf-compressed EXR block runs into an unpopulated decode-table entry mid-decode: the compressed payload is truncated, offset-corrupted, or the header-declared data sizes don't match the actual data.

Common situations: EXR files cut off mid-scanline; offsets corrupted by byte-level data mangling; wrong chunk data lengths from a bad writer; reading a file where huf payload doesn't match its huf code table (e.g. file spliced from two versions).

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/ba82effef3a728f1. Report an issue: GitHub.