BabylonJS/Babylon.js · error

deflate: distance out of range

Error message

deflate: distance out of range

What it means

OutputWriter.copy validates that a back-reference distance is within the bytes already written: distance must be > 0 and <= the current output offset. A distance beyond what has been emitted is illegal in DEFLATE (it would read from the pre-output prefix shared with the compressor), so the library throws. This always indicates a corrupt or non-deflate bitstream, since a valid compressor never emits such a distance.

Source

Thrown at packages/dev/loaders/src/FBX/parsers/zlibInflate.ts:168

    public constructor(expectedLength: number) {
        this.bytes = new Uint8Array(expectedLength);
    }

    public writeByte(value: number): void {
        if (this.offset >= this.bytes.byteLength) {
            throw new Error("zlib: output length mismatch");
        }
        const byte = value & 0xff;
        this.bytes[this.offset++] = byte;
        this.adlerA += byte;
        this.adlerB += this.adlerA;
        this.adlerA %= ADLER_MOD;
        this.adlerB %= ADLER_MOD;
    }

    public copy(distance: number, length: number): void {
        if (distance <= 0 || distance > this.offset) {
            throw new Error("deflate: distance out of range");
        }
        for (let i = 0; i < length; i++) {
            this.writeByte(this.bytes[this.offset - distance]);
        }
    }

    public finish(): void {
        if (this.offset !== this.bytes.byteLength) {
            throw new Error("zlib: output length mismatch");
        }
    }

    public adler32(): number {
        return ((this.adlerB << 16) | this.adlerA) >>> 0;
    }
}

class HuffmanTree {

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Treat the file as corrupt first: try inflating it with pako or Node's zlib to confirm.
  2. Verify the payload slice starts exactly at the compressed data (2-byte zlib header), not at an arbitrary offset.
  3. Re-download/re-export the FBX file; check git LFS pointers and merge states for binary assets.
  4. If you control the producer, regenerate the compressed payload with a standard zlib implementation.

Example fix

// before
const payload = buffer.subarray(nodeOffset + 8, ...); // wrong start, mid-stream
// after
const payload = buffer.subarray(nodeOffset, nodeOffset + compressedLength); // header-aligned start
inflateZlib(payload, count);
Defensive patterns

Strategy: try-catch

Validate before calling

function hasValidZlibHeader(buf: Uint8Array): boolean {
  return buf.byteLength >= 6 && (buf[0] & 0x0f) === 8 && buf[0] >> 4 <= 7 && ((buf[0] << 8) + buf[1]) % 31 === 0;
}
if (!hasValidZlibHeader(payload)) throw new Error("not a zlib stream");

Type guard

function isZlib(buf: unknown): buf is Uint8Array {
  return buf instanceof Uint8Array && buf.byteLength >= 6 && ((buf[0] << 8) + buf[1]) % 31 === 0;
}

Try / catch

try {
  return inflateZlib(payload, count);
} catch (e) {
  if (e instanceof Error && e.message === "deflate: distance out of range") {
    throw new Error("corrupt deflate stream (illegal back-reference) — re-export the FBX asset");
  }
  throw e;
}

Prevention

When it happens

Trigger: inflateCompressedBlock decodes a length/distance pair whose decoded distance exceeds the number of bytes written so far — bitstream desynchronization (e.g. after a truncated read or wrong tree), or input that is not actually deflate data.

Common situations: Corrupted downloads where mid-stream bits flip; passing a random byte blob that passed the zlib header coincidence test; mixing up payload offsets so the inflater starts mid-stream; FBX assets damaged by faulty binary-merge tooling (git LFS/merge conflicts).

Related errors


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