{"record":{"id":"c930c330e2c35bfd","repo":"BabylonJS/Babylon.js","slug":"the-loader-plugin-corresponding-to-the-pluginex","errorCode":null,"errorMessage":"The loader plugin corresponding to the '${pluginExtension}' file type has not been found. If using es6, please import the plugin you wish to use before.","messagePattern":"The loader plugin corresponding to the '(.+?)' file type has not been found\\. If using es6, please import the plugin you wish to use before\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Loading/sceneLoader.ts","lineNumber":734,"sourceCode":"    // much simpler as we can just pass the options to the factory, rather than passing options through to every possible\r\n    // plugin call. Given this, options are only supported for plugins that provide a factory function.\r\n    let plugin: SceneLoaderPlugin;\r\n    if (IsFactory(registeredPlugin.plugin)) {\r\n        const pluginFactory = registeredPlugin.plugin;\r\n        try {\r\n            // Only await when the factory is actually asynchronous, so that for synchronous factories the plugin is\r\n            // instantiated (and onPluginActivatedObservable is notified) synchronously within the calling load operation.\r\n            const createdPlugin = pluginFactory.createPlugin((pluginOptions ?? {}) as SceneLoaderPluginOptions);\r\n            plugin = createdPlugin instanceof Promise ? await createdPlugin : createdPlugin;\r\n        } catch (error) {\r\n            throw createLoadError(fileInfo, \"Error instantiating plugin.\", error);\r\n        }\r\n    } else {\r\n        plugin = registeredPlugin.plugin;\r\n    }\r\n\r\n    if (!plugin) {\r\n        throw new Error(`The loader plugin corresponding to the '${pluginExtension}' file type has not been found. If using es6, please import the plugin you wish to use before.`);\r\n    }\r\n\r\n    onPluginActivatedObservable.notifyObservers(plugin);\r\n\r\n    // Check if we have a direct load url. If the plugin is registered to handle\r\n    // it or it's not a base64 data url, then pass it through the direct load path.\r\n    if (directLoad && ((plugin.canDirectLoad && plugin.canDirectLoad(fileInfo.url)) || !IsBase64DataUrl(fileInfo.url))) {\r\n        if (plugin.directLoad) {\r\n            let data: unknown;\r\n            try {\r\n                data = await plugin.directLoad(scene, directLoad);\r\n            } catch (error) {\r\n                throw createLoadError(fileInfo, \"Error in directLoad of _loadData: \" + error, error);\r\n            }\r\n            return { plugin, data };\r\n        }\r\n        return { plugin, data: directLoad };\r\n    }\r","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Loading/sceneLoader.ts#L716-L752","documentation":"A plugin registration matched the extension metadata, but the actual plugin instance/factory was not available when loading started. This typically happens in ES6/tree-shaking builds where the loader module was never imported, so the factory registry is empty even though the extension string was supplied.","triggerScenarios":"Calling SceneLoader with an explicit pluginExtension (e.g. \"glb\") in an ES6 project without importing \"@babylonjs/loaders/glTF\" (or equivalent) beforehand.","commonSituations":"Vite/webpack tree-shaking removing the loaders package because only SceneLoader was referenced; dynamic-import-based bundlers where loaders load after the scene load begins; UMD-to-ES6 migration dropping global BABYLON loader scripts.","solutions":["Add a side-effect import of the needed loader: import \"@babylonjs/loaders/glTF\"; before any load call.","If using dynamic loading, await the loader module import before calling SceneLoader.","In UMD setups, include the loaders .js script bundle on the page."],"exampleFix":"// before\nimport { SceneLoader } from \"@babylonjs/core\";\nawait SceneLoader.ImportMeshAsync(\"\", root, \"model.glb\", scene); // plugin not found\n\n// after\nimport { SceneLoader } from \"@babylonjs/core\";\nimport \"@babylonjs/loaders/glTF\";\nawait SceneLoader.ImportMeshAsync(\"\", root, \"model.glb\", scene);","handlingStrategy":"fallback","validationCode":"function ensureGlTFLoaded(): void {\n  if (!BABYLON.SceneLoader.IsPluginForExtensionAvailable(\".glb\")) {\n    throw new Error(\"glTF loader not imported — add import '@babylonjs/loaders/glTF'\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await BABYLON.SceneLoader.ImportMeshAsync(\"\", root, file, scene);\n} catch (e) {\n  if ((e as Error).message.includes(\"has not been found\")) {\n    await import(\"@babylonjs/loaders/glTF\");\n    return BABYLON.SceneLoader.ImportMeshAsync(\"\", root, file, scene);\n  }\n}","preventionTips":["Add side-effect imports for every loader format used by the app at the entry point.","Verify with SceneLoader.IsPluginForExtensionAvailable before loading.","Check bundler tree-shaking config does not drop loader side-effect modules."],"tags":["loading","es6","tree-shaking","missing-import"],"backgroundTag":"missing-loader-plugin","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}