{"record":{"id":"0aa8170fb0db5af9","repo":"BabylonJS/Babylon.js","slug":"first-chunk-format-is-not-json","errorCode":null,"errorMessage":"First chunk format is not JSON","messagePattern":"First chunk format is not JSON","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/glTFFileLoader.pure.ts","lineNumber":1334,"sourceCode":"                readAsync: (byteOffset, byteLength) => dataReader.buffer.readAsync(startByteOffset + byteOffset, byteLength),\r\n                byteLength: bodyLength,\r\n            };\r\n        }\r\n\r\n        return Promise.resolve(data);\r\n    }\r\n\r\n    private _unpackBinaryV2Async(dataReader: DataReader, length: number): Promise<IGLTFLoaderData> {\r\n        const ChunkFormat = {\r\n            JSON: 0x4e4f534a,\r\n            BIN: 0x004e4942,\r\n        };\r\n\r\n        // Read the JSON chunk header.\r\n        const chunkLength = dataReader.readUint32();\r\n        const chunkFormat = dataReader.readUint32();\r\n        if (chunkFormat !== ChunkFormat.JSON) {\r\n            throw new Error(\"First chunk format is not JSON\");\r\n        }\r\n\r\n        // Bail if there are no other chunks.\r\n        if (dataReader.byteOffset + chunkLength === length) {\r\n            return dataReader.loadAsync(chunkLength).then(() => {\r\n                return { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };\r\n            });\r\n        }\r\n\r\n        // Read the JSON chunk and the length and type of the next chunk.\r\n        return dataReader.loadAsync(chunkLength + 8).then(() => {\r\n            const data: IGLTFLoaderData = { json: this._parseJson(dataReader.readString(chunkLength)), bin: null };\r\n\r\n            const readAsync = (): Promise<IGLTFLoaderData> => {\r\n                const chunkLength = dataReader.readUint32();\r\n                const chunkFormat = dataReader.readUint32();\r\n\r\n                switch (chunkFormat) {\r","sourceCodeStart":1316,"sourceCodeEnd":1352,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/glTFFileLoader.pure.ts#L1316-L1352","documentation":"Thrown while unpacking a glTF binary v2 container when the first chunk's format uint32 is not ChunkFormat.JSON (0x4E4F534A, 'JSON'). The glb spec mandates the JSON chunk come first.","triggerScenarios":"Loading a .glb whose first chunk header declares a non-JSON format (e.g. BIN first, or a corrupted format value).","commonSituations":"Custom .glb writers that emit the BIN chunk first; files corrupted in transfer/storage; tools writing v1 layout into a v2 header.","solutions":["Re-export the .glb with a spec-compliant tool so the JSON chunk is first","Hex-inspect the chunk header at byte 12–20 and correct the format field","Run glTF-Validator on the file to confirm container layout"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const dv = new DataView(await file.arrayBuffer());\nif (dv.getUint32(0, true) !== 0x46546c67) throw new Error('not glb');\nif (dv.getUint32(4, true) === 2 && dv.getUint32(16, true) !== 0x4e4f534a) {\n  throw new Error('First glb-v2 chunk is not JSON');\n}","typeGuard":"function firstChunkIsJson(buf: ArrayBuffer): boolean {\n  return new DataView(buf).getUint32(16, true) === 0x4e4f534a; // 'JSON'\n}","tryCatchPattern":"try {\n  await loader.loadAsync(url);\n} catch (e) {\n  if (e.message === 'First chunk format is not JSON') {\n    console.error('glb chunk order violated — re-export with a compliant tool');\n  }\n}","preventionTips":["Ensure JSON chunk always comes first when writing .glb files","Use glTF-Transform instead of custom glb writers","Validate containers before publishing"],"tags":["gltf","binary","file-format"],"backgroundTag":"invalid-file-magic","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}