{"record":{"id":"24a408c4862fbf29","repo":"BabylonJS/Babylon.js","slug":"zlib-invalid-header","errorCode":null,"errorMessage":"zlib: invalid header","messagePattern":"zlib: invalid header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/FBX/parsers/zlibInflate.ts","lineNumber":28,"sourceCode":"\r\n/**\r\n * Inflate a zlib-wrapped deflate stream.\r\n *\r\n * This implementation is intentionally scoped to FBX binary array payloads: one-shot,\r\n * synchronous zlib streams with the exact uncompressed length known up front.\r\n */\r\nexport function inflateZlib(input: Uint8Array, expectedLength: number): Uint8Array {\r\n    if (!Number.isInteger(expectedLength) || expectedLength < 0) {\r\n        throw new Error(\"zlib: invalid expected length\");\r\n    }\r\n    if (input.byteLength < 6) {\r\n        throw new Error(\"zlib: unexpected end of input\");\r\n    }\r\n\r\n    const cmf = input[0];\r\n    const flg = input[1];\r\n    if ((cmf & 0x0f) !== 8 || cmf >> 4 > 7 || ((cmf << 8) + flg) % 31 !== 0) {\r\n        throw new Error(\"zlib: invalid header\");\r\n    }\r\n    if ((flg & 0x20) !== 0) {\r\n        throw new Error(\"zlib: preset dictionary not supported\");\r\n    }\r\n\r\n    const reader = new BitReader(input, 2, input.byteLength - 4);\r\n    const output = new OutputWriter(expectedLength);\r\n\r\n    let isFinalBlock = false;\r\n    while (!isFinalBlock) {\r\n        isFinalBlock = reader.readBits(1) === 1;\r\n        const blockType = reader.readBits(2);\r\n        switch (blockType) {\r\n            case 0:\r\n                inflateStoredBlock(reader, output);\r\n                break;\r\n            case 1:\r\n                inflateCompressedBlock(reader, output, getFixedLiteralLengthTree(), getFixedDistanceTree());\r","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/FBX/parsers/zlibInflate.ts#L10-L46","documentation":"The first two bytes of a zlib stream (CMF/FLG) must declare the deflate method (CMF&0x0f === 8), window size ≤ 32K (CMF>>4 ≤ 7), and pass the header checksum ((CMF<<8|FLG) % 31 === 0). inflateZlib throws 'zlib: invalid header' when the buffer's first bytes are not a valid zlib header.","triggerScenarios":"parseArrayProperty hands inflateZlib bytes that are not actually zlib-compressed — e.g., an FBX record with encoding set to 1 but raw/uncompressed data, data starting at the wrong offset (off-by-a-few-bytes), or a differently-compressed payload (gzip, lzma) mislabeled as zlib.","commonSituations":"FBX files written by non-standard exporters that set the encoding flag without actually zlib-compressing; misaligned parsing due to a bad earlier field; assets processed by a pipeline that recompressed arrays with a different codec.","solutions":["Confirm the FBX record's encoding flag matches its actual content — re-export the file from the original tool","Check the byte offset used to locate the compressed payload; off-by-N errors surface as header failures","Inspect the first bytes: a valid zlib stream starts with 0x78 typically; 0x1F8B means gzip, plain text means not compressed","Validate with a reference FBX reader; if it also fails, the file is malformed"],"exampleFix":"// before\nconst compressed = bytes.slice(offset + 4, offset + len);\n// after\nconst compressed = bytes.slice(offset, offset + len); // correct header offset\nif (compressed[0] !== 0x78) console.warn('FBX array payload is not zlib data at offset', offset);","handlingStrategy":"validation","validationCode":"function looksLikeZlib(b: Uint8Array): boolean {\n  if (b.byteLength < 2) return false;\n  const cmf = b[0], flg = b[1];\n  return (cmf & 0x0f) === 8 && (cmf >> 4) <= 7 && ((cmf << 8) + flg) % 31 === 0;\n}\nif (!looksLikeZlib(compressed)) throw new Error('FBX array payload is not zlib data');","typeGuard":"function isZlibStream(b: Uint8Array): boolean {\n  return b.byteLength >= 2 && (b[0] & 0x0f) === 8 && (b[0] >> 4) <= 7 && ((b[0] << 8) + b[1]) % 31 === 0;\n}","tryCatchPattern":"try {\n  return inflateZlib(compressed, expectedLength);\n} catch (e) {\n  if ((e as Error).message === 'zlib: invalid header') {\n    throw new Error('FBX compressed array does not contain a valid zlib stream', { cause: e });\n  }\n  throw e;\n}","preventionTips":["Check the first byte is 0x78-family before inflating","Ensure the compressed region starts at the correct record offset","Avoid pipelines that relabel gzip/lzma data as zlib"],"tags":["zlib","compression","corrupt-data","fbx"],"backgroundTag":"zlib-invalid-header","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}