{"record":{"id":"4d2c2fcbe9605f28","repo":"BabylonJS/Babylon.js","slug":"invalid-fbx-node-end-offset-endoffset-at-offset","errorCode":null,"errorMessage":"Invalid FBX node end offset ${endOffset} at offset ${offset}","messagePattern":"Invalid FBX node end offset (.+?) at offset (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts","lineNumber":75,"sourceCode":"        ensureRange(bytes, offset, 25, limit, \"FBX node header\");\r\n        endOffset = readUint64AsNumber(view, offset);\r\n        numProperties = readUint64AsNumber(view, offset + 8);\r\n        propertyListLen = readUint64AsNumber(view, offset + 16);\r\n        headerSize = 25; // 8+8+8+1 (nameLen byte)\r\n    } else {\r\n        ensureRange(bytes, offset, 13, limit, \"FBX node header\");\r\n        endOffset = view.getUint32(offset, true);\r\n        numProperties = view.getUint32(offset + 4, true);\r\n        propertyListLen = view.getUint32(offset + 8, true);\r\n        headerSize = 13; // 4+4+4+1 (nameLen byte)\r\n    }\r\n\r\n    // Null sentinel: all header fields are zero\r\n    if (endOffset === 0) {\r\n        return null;\r\n    }\r\n    if (endOffset <= offset || endOffset > limit) {\r\n        throw new Error(`Invalid FBX node end offset ${endOffset} at offset ${offset}`);\r\n    }\r\n\r\n    const nameLen = bytes[offset + headerSize - 1];\r\n    ensureRange(bytes, offset + headerSize, nameLen, endOffset, \"FBX node name\");\r\n    const name = decodeASCII(bytes, offset + headerSize, nameLen);\r\n\r\n    let cursor = offset + headerSize + nameLen;\r\n    const propertiesStart = cursor;\r\n    const propertiesEnd = propertiesStart + propertyListLen;\r\n    if (propertiesEnd > endOffset) {\r\n        throw new Error(`Invalid FBX property list length for node '${name}' at offset ${offset}`);\r\n    }\r\n\r\n    // Parse properties\r\n    const properties: FBXProperty[] = [];\r\n    for (let i = 0; i < numProperties; i++) {\r\n        const result = parseProperty(view, bytes, cursor, propertiesEnd);\r\n        properties.push(result.property);\r","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/FBX/parsers/fbxBinaryParser.ts#L57-L93","documentation":"Each binary FBX node record starts with an end-offset field. The offset-based bounds check in parseNode requires endOffset to be strictly greater than the node's own offset and within the parent's limit; values of 0 are the legal null sentinel (handled above), so any other out-of-range value means the record header is corrupt or the assumed header layout (32-bit vs 64-bit) is wrong.","triggerScenarios":"Parsing node records (via `result`/`child` recursion) where the read endOffset is <= current offset or exceeds the parse limit — typically caused by a corrupted file, or by reading a v7.5+ (64-bit header) file with the 32-bit header layout when version detection failed.","commonSituations":"FBX files ≥7500 exported with unusual headers misread due to a wrong version at offset 23; bit-flipped/corrupted downloads; third-party exporters writing non-conformant node records.","solutions":["Verify the FBX version read at byte 23 is correct for the file (≥7500 ⇒ 64-bit offsets); dump the first 32 bytes to inspect","Re-export the FBX (try both binary FBX 2014/2016 and 2020) from the source tool","Re-download the file — corruption in transit is the most common cause","Compare against a known-good FBX with the same version to check header layout assumptions"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const v = new DataView(buffer).getUint32(23, true);\nif (v < 6000 || v > 10000) throw new Error(`Implausible FBX version ${v}`); // also flags layout mismatch","typeGuard":"function hasPlausibleFbxVersion(buf) {\n  if (buf.byteLength < 27) return false;\n  const version = new DataView(buf).getUint32(23, true);\n  return version >= 6000 && version <= 10000;\n}","tryCatchPattern":"try {\n  const doc = parseBinaryFBX(buffer);\n} catch (e) {\n  if (/Invalid FBX node end offset/.test(e.message)) {\n    console.error(\"Node record out of bounds — file corrupt or 32/64-bit header mismatch; re-export FBX\");\n  } else throw e;\n}","preventionTips":["Confirm version ≥7500 files use 64-bit node headers","Checksum-verify downloads before parsing","Re-export via Autodesk FBX Converter when a tool produces non-conformant records","Treat parser bound errors as corrupt-file signals, not retryable faults"],"tags":["fbx","binary","corrupt","offset","record-layout"],"backgroundTag":"fbx-corrupt-record","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}