{"record":{"id":"f8bf09a4e847b32f","repo":"BabylonJS/Babylon.js","slug":"invalid-fbx-child-node-end-offset-child-endoffse","errorCode":null,"errorMessage":"Invalid FBX child node end offset ${child.endOffset} at offset ${cursor}","messagePattern":"Invalid FBX child node end offset (.+?) at offset (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts","lineNumber":109,"sourceCode":"    for (let i = 0; i < numProperties; i++) {\r\n        const result = parseProperty(view, bytes, cursor, propertiesEnd);\r\n        properties.push(result.property);\r\n        cursor = result.nextOffset;\r\n    }\r\n    if (cursor !== propertiesEnd) {\r\n        throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\r\n    }\r\n\r\n    // Parse nested child nodes (between end of properties and endOffset)\r\n    const children: FBXNode[] = [];\r\n    if (cursor < endOffset) {\r\n        while (cursor < endOffset) {\r\n            const child = parseNode(view, bytes, cursor, is64Bit, endOffset);\r\n            if (child === null) {\r\n                break;\r\n            }\r\n            if (child.endOffset <= cursor || child.endOffset > endOffset) {\r\n                throw new Error(`Invalid FBX child node end offset ${child.endOffset} at offset ${cursor}`);\r\n            }\r\n            children.push(child.node);\r\n            cursor = child.endOffset;\r\n        }\r\n    }\r\n\r\n    return {\r\n        node: { name, properties, children },\r\n        endOffset,\r\n    };\r\n}\r\n\r\ninterface ParsedProperty {\r\n    property: FBXProperty;\r\n    nextOffset: number;\r\n}\r\n\r\nfunction parseProperty(view: DataView, bytes: Uint8Array, offset: number, limit: number): ParsedProperty {\r","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts#L91-L127","documentation":"Nested child node records must lie strictly inside their parent: each child's endOffset must be greater than the child's own start cursor and not exceed the parent's endOffset. A child reporting endOffset outside that window indicates a corrupt record or a header-layout (32/64-bit) mismatch during recursive parsing.","triggerScenarios":"The child-parsing loop in parseNode (via `result`/`child`) reads a nested node whose decoded endOffset is <= cursor or > parent endOffset — typically corruption, or a 64-bit-offset file parsed with the 32-bit reader when the version check at byte 23 failed.","commonSituations":"FBX 7.5+ files with unusual version fields; corrupted transfers; files stitched/merged incorrectly; fuzzed inputs.","solutions":["Confirm the version field at byte offset 23 matches the actual FBX version so the correct (32/64-bit) header size is used","Re-download/re-export the file to eliminate corruption","Validate against the FBX binary spec by hexdumping the child record header at `cursor`","Add a pre-parse guard that rejects files whose version field is implausible (0 or > 10000)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const version = new DataView(buffer).getUint32(23, true);\nif (!(version >= 6000 && version <= 10000)) throw new Error(\"Implausible FBX version — likely wrong/corrupt file\");\n// ensure 64-bit layout is applied for >= 7500 (parser does this; the check catches corrupt version fields)","typeGuard":"function fbxLayoutOk(buf) {\n  if (buf.byteLength < 27) return false;\n  const v = new DataView(buf).getUint32(23, true);\n  return v >= 6000 && v <= 10000;\n}","tryCatchPattern":"try {\n  const doc = parseBinaryFBX(buffer);\n} catch (e) {\n  if (/Invalid FBX child node end offset/.test(e.message)) {\n    console.error(\"Nested FBX node out of parent bounds — corrupt record or header-layout mismatch; re-export the FBX\");\n  } else throw e;\n}","preventionTips":["Verify the version field matches the exporter's stated FBX version (7.4 ⇒ 7400, 7.5+ ⇒ 32/64-bit switch)","Checksum files after transfer; discard corrupt copies","Normalize third-party FBX through a converter before ingestion","Don't merge/stitch FBX binaries manually"],"tags":["fbx","binary","corrupt","child-node","bounds"],"backgroundTag":"fbx-corrupt-record","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}