BabylonJS/Babylon.js · error

zlib: adler32 mismatch

Error message

zlib: adler32 mismatch

What it means

zlib streams end with an Adler-32 checksum of the uncompressed data. inflateZlib computes the checksum of what it inflated and compares it to the trailer; a mismatch throws 'zlib: adler32 mismatch', meaning the data decompressed without error but is not the data that was compressed — silent corruption.

Source

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

                break;
            case 2: {
                const { literalLengthTree, distanceTree } = readDynamicTrees(reader);
                inflateCompressedBlock(reader, output, literalLengthTree, distanceTree);
                break;
            }
            default:
                throw new Error("deflate: invalid block type");
        }
    }

    if (reader.byteOffset < input.byteLength - 4) {
        throw new Error("zlib: trailing deflate data");
    }

    output.finish();
    const expectedAdler = ((input[input.byteLength - 4] << 24) | (input[input.byteLength - 3] << 16) | (input[input.byteLength - 2] << 8) | input[input.byteLength - 1]) >>> 0;
    if (output.adler32() !== expectedAdler) {
        throw new Error("zlib: adler32 mismatch");
    }

    return output.bytes;
}

class BitReader {
    private bitBuffer = 0;
    private bitCount = 0;

    public constructor(
        private readonly input: Uint8Array,
        public byteOffset: number,
        private readonly endOffset: number
    ) {}

    public readBits(count: number): number {
        this.ensureBits(count);
        const value = this.bitBuffer & ((1 << count) - 1);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Re-download or re-export the FBX file and verify its hash
  2. Confirm the trailer used is the last 4 bytes of the same compressed buffer (no extra/missing bytes)
  3. If you control generation, recompress the payload so the Adler-32 matches
  4. Treat repeated mismatches across files as a transfer-layer problem (e.g., FTP ASCII mode) and switch to binary-safe transfer

Example fix

// before
const data = fs.readFileSync(p).slice(off, off + len); // trailer from stale slice
// after
const end = off + declaredCompressedLength; const data = fs.readFileSync(p).slice(off, end); // trailer = last 4 bytes of this buffer
Defensive patterns

Strategy: try-catch

Validate before calling

// verify whole-file integrity before parse so corruption is caught early
if (sha256(await fs.readFile(path)) !== manifestHash) {
  throw new Error('FBX file failed integrity check');
}

Try / catch

try {
  return inflateZlib(compressed, expectedLength);
} catch (e) {
  if ((e as Error).message === 'zlib: adler32 mismatch') {
    throw new Error('FBX compressed array failed checksum — file is corrupted in transfer or storage', { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: Any bit corruption inside the compressed payload that the deflate decoder tolerated, wrong expectedAdler byte order or trailer offset (e.g., trailing bytes present), or the output buffer's expected length differing from the original stream length.

Common situations: Damaged files (network/storage corruption) that still inflate cleanly; payload extracted from a container with stale/incorrect trailer bytes; custom pipelines that recompress data but copy an old checksum.

Related errors


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