{"record":{"id":"f8b8651fd1ba4e12","repo":"BabylonJS/Babylon.js","slug":"path-path-is-invalid-no-length-accessor","errorCode":null,"errorMessage":"Path ${path} is invalid - no length accessor","messagePattern":"Path (.+?) is invalid - no length accessor","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/2.0/Extensions/gltfPathToObjectConverter.ts","lineNumber":100,"sourceCode":"        //if the last part has \".length\" in it, separate that as an extra part\r\n        if (parts[parts.length - 1].includes(\".length\")) {\r\n            const lastPart = parts[parts.length - 1];\r\n            const split = lastPart.split(\".\");\r\n            parts.pop();\r\n            parts.push(...split);\r\n        }\r\n\r\n        let ignoreObjectTree = false;\r\n\r\n        for (const part of parts) {\r\n            const isLength = part === \"length\";\r\n            if (isLength) {\r\n                // For .length, check if the current level has a 'length' accessor\r\n                if (infoTree.length) {\r\n                    infoTree = infoTree.length;\r\n                } else if (infoTree.__array__) {\r\n                    // Fallback: length of an array that doesn't have explicit length accessor\r\n                    throw new Error(`Path ${path} is invalid - no length accessor`);\r\n                } else {\r\n                    throw new Error(`Path ${path} is invalid`);\r\n                }\r\n                // Set target to the current object tree (the array itself)\r\n                // Only update target if objectTree is defined, otherwise keep the last valid target\r\n                if (objectTree !== undefined) {\r\n                    target = objectTree;\r\n                }\r\n                continue;\r\n            }\r\n            if (infoTree.__ignoreObjectTree__) {\r\n                ignoreObjectTree = true;\r\n            }\r\n            if (infoTree.__array__) {\r\n                infoTree = infoTree.__array__;\r\n            } else {\r\n                infoTree = infoTree[part];\r\n                if (!infoTree) {\r","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/2.0/Extensions/gltfPathToObjectConverter.ts#L82-L118","documentation":"GLTFPathToObjectConverter.convert() resolves a glTF Object Model JSON Pointer against the loader's info tree. When the last path segment is `.length`, the library expects the current info level to either expose a dedicated `length` accessor or to be a typed array (`__array__`) whose length can be computed. This throw fires when the path ends in `.length` on a level that is an array container (`__array__`) but defines no `length` accessor, so the loader cannot compute a length for it.","triggerScenarios":"Calling convert() (directly or via KHR_animation_pointer / KHR_interactivity property resolution) with a pointer such as `/nodes.length` where the info tree entry for `nodes` is marked `__array__` but has no `length` info defined, or `.length` applied to a non-array property.","commonSituations":"A glTF asset's interactivity/animation graph references an array length pointer that the Babylon object model definition does not implement; using a `.length` pointer on an extension-defined array that has no length metadata.","solutions":["Use a pointer without the `.length` suffix, or point at a property that the Babylon glTF object model defines a `length` accessor for","Check the Babylon glTF Object Model docs to confirm the array supports a length pointer","If you own the info tree definition (extension author), add a `length` accessor entry to the array's info tree","Upgrade Babylon.js - support for implicit array lengths has changed across versions"],"exampleFix":"// before\nconverter.convert(\"/nodes.length\"); // throws if no length accessor defined\n// after\nconst hasLength = \"/nodes.length\" in supportedPointers; // or use a concrete property\nconverter.convert(\"/nodes/0/translation\");","handlingStrategy":"validation","validationCode":"const supportedLengthPointers = [\"/nodes.length\", \"/meshes.length\", \"/materials.length\", \"/animations.length\"];\nif (path.endsWith(\".length\") && !supportedLengthPointers.includes(path)) {\n    throw new Error(`Refusing to bind unsupported length pointer: ${path}`);\n}","typeGuard":"function isKnownArrayRoot(path: string, gltf: any): boolean {\n    const root = path.replace(/^\\//, \"\").replace(/\\.length$/, \"\");\n    return Array.isArray(gltf?.[root]);\n}","tryCatchPattern":"try {\n    accessor = converter.convert(path);\n} catch (e) {\n    if (String(e.message).includes(\"no length accessor\")) {\n        accessor = null; // fall back to manual array.length lookup\n    } else throw e;\n}","preventionTips":["Only use .length suffixes on top-level glTF arrays documented in the Object Model","Validate pointers against the glTF Object Model spec at asset-import time","Log the full path in the error handler to identify the offending graph node","Pin and test with the Babylon version your assets target"],"tags":["gltf","json-pointer","path-resolution","khr-animation-pointer"],"backgroundTag":"invalid-gltf-pointer","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}