{"record":{"id":"687ed0adffdfd6cf","repo":"BabylonJS/Babylon.js","slug":"required-extension-name-is-not-available","errorCode":null,"errorMessage":"Required extension ${name} is not available","messagePattern":"Required extension (.+?) is not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts","lineNumber":736,"sourceCode":"                        return extension;\r\n                    })()\r\n                );\r\n            }\r\n        });\r\n\r\n        this._extensions.push(...(await Promise.all(extensionPromises)));\r\n\r\n        this._extensions.sort((a, b) => (a.order || Number.MAX_VALUE) - (b.order || Number.MAX_VALUE));\r\n        this._parent.onExtensionLoadedObservable.clear();\r\n\r\n        if (this._gltf.extensionsRequired) {\r\n            for (const name of this._gltf.extensionsRequired) {\r\n                const available = this._extensions.some((extension) => extension.name === name && extension.enabled);\r\n                if (!available) {\r\n                    if (this.parent.extensionOptions[name]?.enabled === false) {\r\n                        throw new Error(`Required extension ${name} is disabled`);\r\n                    }\r\n                    throw new Error(`Required extension ${name} is not available`);\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    private _createRootNode(): INode {\r\n        if (this._parent.customRootNode !== undefined) {\r\n            this._rootBabylonMesh = this._parent.customRootNode;\r\n            return {\r\n                _babylonTransformNode: this._rootBabylonMesh === null ? undefined : this._rootBabylonMesh,\r\n                index: -1,\r\n            };\r\n        }\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        const rootMesh = new Mesh(\"__root__\", this._babylonScene);\r\n        this._rootBabylonMesh = rootMesh;\r\n        this._rootBabylonMesh._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r","sourceCodeStart":718,"sourceCodeEnd":754,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts#L718-L754","documentation":"The glTF asset lists an extension in its 'extensionsRequired' array, but no registered loader extension with that name is available (or it is not enabled). Since 'extensionsRequired' means the client MUST support the extension to render the asset, the loader aborts rather than produce a broken result.","triggerScenarios":"Loading a .glb/.gltf that requires e.g. KHR_draco_mesh_compression, KHR_texture_basisu, or EXT_meshopt_compression without registering the corresponding Babylon extension plugin.","commonSituations":"Exporting from Blender/DCC with Draco or meshopt compression but not wiring the decoder or extension plugin in the app; forgetting to import the extension package (tree-shaking removed it); using a viewer subset of the library that excludes optional loaders.","solutions":["Import and register the required extension loader (e.g. GLTFLoaderDracoCompression, GLTFLoaderMeshoptCompression, GLTFLoader KhronosTextureContainer2) before loading","Provide the necessary decoder/decoder binaries (Draco decoder URL, meshopt decoder, KTX2 decoder) via loader options","Re-export the asset without the compression/extension if the runtime cannot support it","Check the asset's extensionsRequired array and compare with the enabled this._extensions list"],"exampleFix":"// before\nconst loader = new GLTFLoader();\nconst data = await loader.loadAsync(\"/scenes/model.glb\"); // throws: KHR_draco_mesh_compression not available\n// after\nimport { GLTFLoaderDracoCompression } from \"loaders/glTF/2.0/Extensions/DRACOLoader\";\nconst loader = new GLTFLoader();\nloader.registerPlugin(new GLTFLoaderDracoCompression(loader));\nloader.dracoDecoder = { url: \"/lib/draco/\" };\nconst data = await loader.loadAsync(\"/scenes/model.glb\");","handlingStrategy":"validation","validationCode":"// Ensure every required extension plugin is registered before loading\nconst registered = new Set(loader._extensions?.map(e => e.name) ?? []); // or track registrations yourself\nfor (const name of gltf.extensionsRequired ?? []) {\n  if (!registered.has(name)) console.warn(`Register plugin for ${name} before loading`);\n}","typeGuard":"function allRequiredExtensionsRegistered(registeredNames, gltf) {\n  const required = gltf.extensionsRequired ?? [];\n  return required.every(name => registeredNames.includes(name));\n}","tryCatchPattern":"try {\n  await loader.loadAsync(url);\n} catch (e) {\n  if (/is not available$/.test(e.message)) {\n    const ext = e.message.match(/Required extension (\\S+) is not available/)?.[1];\n    console.error(`Add support for ${ext} (decoder/plugin) or re-export without it`);\n  } else throw e;\n}","preventionTips":["Register Draco/meshopt/KTX2 plugins and decoders up front in a shared loader factory","Validate assets with glTF-Validator to know which extensions are required","Check imports so tree-shaking does not drop optional loader extensions"],"tags":["gltf","extensions","missing-plugin"],"backgroundTag":"required-gltf-extension-missing","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}