# Gltf loader error when upgrading to BabylonJS 8.51.2 from 8.24.0

**URL:** <https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447>\
**Category:** Bugs\
**Tags:** gltffileloader\
**Created:** [February 15, 2026, 5:09am UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447 "2026-02-15T05:09:03Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 15, 2026, 5:09am UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/1 "2026-02-15T05:09:03Z")

</div>

While attempting to upgrade my project from BabylonJS 8.24 to the latest version, I ran into this rather ugly exception:

```plaintext
Uncaught _RuntimeError RuntimeError: Unable to load from ./models/PlayerVisual.glb: Unsupported version: 2.0
    at errorHandler (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:896:42)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:969:25)
    --- Promise.catch ---
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:968:22)
    at dataCallback (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:683:13)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\loaders\src\glTF\glTFFileLoader.ts:877:29)
    --- Promise.then ---
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\loaders\src\glTF\glTFFileLoader.ts:875:23)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:539:13)
    at onReadyStateChange (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:697:37)
    --- XMLHttpRequest.send ---
    at send (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\webRequest.ts:185:19)
    at retryLoop (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:728:21)
    at requestFile (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:731:9)
    at RequestFile (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:774:9)
    at LoadFile (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Misc\fileTools.ts:536:12)
    at _loadFile (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\scene.ts:6289:25)
    at _loadFile (c:\Dev\BabylonJS\kitchen-chaos\dev\loaders\src\glTF\glTFFileLoader.ts:1116:31)
    at loadFile (c:\Dev\BabylonJS\kitchen-chaos\dev\loaders\src\glTF\glTFFileLoader.ts:865:25)
    at manifestChecked (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:714:26)
    at _Database (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Offline\database.ts:69:13)
    at AbstractEngine.OfflineProviderFactory (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Offline\database.ts:11:12)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:735:52)
    at getPluginInstance (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:634:17)
    at loadDataAsync (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:643:12)
    at importMeshAsync (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:929:18)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:994:13)
    at importMeshAsyncCoreAsync (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:992:18)
    at ImportMeshAsync (c:\Dev\BabylonJS\kitchen-chaos\dev\core\src\Loading\sceneLoader.ts:860:18)
    at loadActors (c:\Dev\BabylonJS\kitchen-chaos\src\stages\GameStage.ts:94:28)
    at createScene (c:\Dev\BabylonJS\kitchen-chaos\src\stages\GameStage.ts:37:14)
    at load (c:\Dev\BabylonJS\kitchen-chaos\src\framework\Stage.ts:29:20)
    at setActiveStage (c:\Dev\BabylonJS\kitchen-chaos\src\framework\StageManager.ts:255:29)
    at start (c:\Dev\BabylonJS\kitchen-chaos\src\main.ts:18:28)
    at <anonymous> (c:\Dev\BabylonJS\kitchen-chaos\src\main.ts:53:12)

```

Inspecting the GLB’s strings, I can see the JSON is properly set to “2.0”.

`glTF`  
`JSON{`  
`"asset": {`  
`"generator": "FBX2glTF v0.9.7",`  
`"version": "2.0"`  
`"scene": 0,`  
`"buffers": [`

The code block I have to load the model is:

```typescript
        let result = await ImportMeshAsync("./models/PlayerVisual.glb", super.scene);

        const PlayerVisual = result.meshes[0];

        PlayerVisual.position = Vector3.Zero();;

        PlayerVisual.rotation = Vector3.Zero();;

        PlayerVisual.receiveShadows = true;

        this._shadowGenerator?.addShadowCaster(PlayerVisual);

```

I tried to recreate this on the [playground](https://playground.babylonjs.com/#HN9OB3), but it is using a deprecated call.

I’ve debugged the source, which is as follows:

```typescript
    private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {
        const asset = (<any>loaderData.json).asset || {};

        this._log(`Asset version: ${asset.version}`);
        asset.minVersion && this._log(`Asset minimum version: ${asset.minVersion}`);
        asset.generator && this._log(`Asset generator: ${asset.generator}`);

        const version = GLTFFileLoader._parseVersion(asset.version);
        if (!version) {
            throw new Error("Invalid version: " + asset.version);
        }

        if (asset.minVersion !== undefined) {
            const minVersion = GLTFFileLoader._parseVersion(asset.minVersion);
            if (!minVersion) {
                throw new Error("Invalid minimum version: " + asset.minVersion);
            }

            if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) {
                throw new Error("Incompatible minimum version: " + asset.minVersion);
            }
        }

        const createLoaders: { [key: number]: (parent: GLTFFileLoader) => IGLTFLoader } = {
            1: GLTFFileLoader._CreateGLTF1Loader,
            2: GLTFFileLoader._CreateGLTF2Loader,
        };

        const createLoader = createLoaders[version.major];
        if (!createLoader) {
            throw new Error("Unsupported version: " + asset.version);

```

and inspecting `version.major` I can see that `2` is passed in. I’m somewhat stuck at this point.

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 15, 2026, 5:10am UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/2 "2026-02-15T05:10:17Z")

</div>

The full source for my project, using 8.24.0, is at [GitHub - Corysia/kitchen-chaos](https://github.com/corysia/kitchen-chaos)

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [February 16, 2026, 8:36am UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/3 "2026-02-16T08:36:54Z")

</div>

cc @bghgary, but it looks like the loader for glTF v2 can’t be found. Make sure the v2 loader is packaged in your project.

> [@Corysia](#):
>
> and inspecting `version.major` I can see that `2` is passed in. I’m somewhat stuck at this point.

You should look at the `createLoaders` object and see if there’s a “2” entry inside: if not, the v2 loader has not been found.

[EDIT]

Package.json:

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/a/a/aa21119aba3ff55286598649246b2e4a7a9376fb.png)

You should have an entry for `@babylonjs/loaders` here.

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 16, 2026, 3:26pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/4 "2026-02-16T15:26:55Z")

</div>

So, is there a change requiring loaders to be included differently than in version 8.24? I am only upgrading the version of BabylonJS I’m using from 8.24 to 8.51. This is working fine in 8.24, crashing in 8.51.

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 16, 2026, 4:38pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/5 "2026-02-16T16:38:58Z")

</div>

When I inspect the array, there are two `undefined` entries.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/a/0/a03946487bc7d34e7fefbd9a71e3544f461e846c.png)

I’ve also updated package.json to include loaders in my local branch, but it did not help:

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/6/c/6c89a668c56896cdfa4e4523c16559532f997439.png)

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 16, 2026, 4:52pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/6 "2026-02-16T16:52:28Z")

</div>

It appears that now the latest version of BabylonJS, you must import the loaders to initialize them. The change in `package.json` isn’t necessary, but an import statement is.

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/c/e/ce35d7961d5e7b6f3d2d05ffc41e61188ec263d7.png)

---

<div class="post-metadata">

**Author:** ![bghgary](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/bghgary/32/48532_2.png) [@bghgary](https://forum.babylonjs.com/u/bghgary)\
**Post date:** [February 18, 2026, 12:45am UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/7 "2026-02-18T00:45:00Z")

</div>

Adding @ryantrem to confirm.

---

<div class="post-metadata">

**Author:** ![ryantrem](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ryantrem/32/34010_2.png) [@ryantrem](https://forum.babylonjs.com/u/ryantrem)\
**Post date:** [February 18, 2026, 4:36pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/8 "2026-02-18T16:36:35Z")

</div>

Scene loaders (e.g. the gltf loader) must be registered for them to be picked up by the general scene loading APIs (e.g. `ImportMeshAsync`). There are currently two ways for them to be registered:

1. Side effects: this is basically the legacy way, and happens when you `import "@babylonjs/loaders"` (or for gltf specifically, it could be just `@babylonjs/loaders/glTF/2.0`).
2. Explicit and dynamic: this is the newer way, and happens when you `import { registerBuiltInLoaders } from "@babylonjs/loaders/dynamic"` and then call `registerBuiltInLoaders()`. This does dynamic imports of loaders and glTF extensions until they are needed.

If you previously weren’t doing either of these, then my best guess is that the switch from 8.24.0 to 8.51.2 is also going from Inspector v1 to v2, and v1 probably had side effects that v2 doesn’t. Whether Inspector has side effects is an implementation detail, so you shouldn’t rely on what is happening inside Inspector to get loaders registered. I would say the robust solution is to use one of the options above to explicitly register loaders, such that if you removed the Inspector package (a diagnostic tool that you typically wouldn’t ship with an app), your app still works.

So basically the change you made (to explicitly `import "@babylonjs/loaders"`) is correct, and you could also improve that by using the newer `registerBuiltInLoaders`.

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 18, 2026, 8:25pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/9 "2026-02-18T20:25:39Z")

</div>

Unfortunately, I’m still stuck. The application is running fine locally, but failing when I deploy to GitHub Pages. And that really surprises me.

I’ve made the suggested changes from above. I’ve also turned off WebGPU and now force WebGL. I’ve disabled minify.

I’ve successfully upgraded to 8.37.3, still failing with 8.51.2. I will continue to make iterative upgrades until it breaks; maybe something will jump out at me. Right now, my console is showing:

```plaintext
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] Main::constructor()
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] Application initialized.
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] this is a warning
warn @ index-Crai-6FJ.js:3365
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] this is an error
error @ index-Crai-6FJ.js:3365
index-Crai-6FJ.js:3365 this is a trace message
trace @ index-Crai-6FJ.js:3365
addEventListeners @ index-Crai-6FJ.js:28694
UEt @ index-Crai-6FJ.js:28694
(anonymous) @ index-Crai-6FJ.js:28694
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] this is a debug message
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] Main::start()
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] StageManager::addStage(): GameStage
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] StageManager::constructor()
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] StageManager: Creating stable WebGL engine (WebGPU disabled)
index-Crai-6FJ.js:23 BJS - [12:15:20]: Babylon.js v8.51.2 - WebGL2 - Parallel shader compilation
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] StageManager: WebGL engine created successfully
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] StageManager::findStage(): GameStage
index-Crai-6FJ.js:3365 [2/18/2026, 12:15:20 PM] Starting to load PlayerVisual.glb

```

I should be receiving a log message after it’s loaded and set up, but I’m not reaching it.

```typescript
        try {
            Logger.debug('Starting to load PlayerVisual.glb');
            let result = await ImportMeshAsync('./models/PlayerVisual.glb', super.scene);
            const PlayerVisual = result.meshes[0];
            PlayerVisual.position = Vector3.Zero();;
            PlayerVisual.rotation = Vector3.Zero();;
            PlayerVisual.receiveShadows = true;
            this._shadowGenerator?.addShadowCaster(PlayerVisual);
            Logger.debug("PlayerVisual.glb loaded successfully");

```

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 18, 2026, 9:18pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/10 "2026-02-18T21:18:32Z")

</div>

I’ve determined that:

1. It fails only on a production build. i.e., `tsc && vite build`
2. It works in GitHub tag `8.48.0` and fails in `8.49.0`. There are no other builds of 8.48 that are tagged on GitHub.
3. It does not fail on a test build in 8.51.2. i.e., `vite –-host`

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 19, 2026, 4:10pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/11 "2026-02-19T16:10:16Z")

</div>

This morning I upgraded to 8.52.0 to see if anything changed. It didn’t, sadly. So I started tracing the code produced in dist and I make it to this point where it freezes:

 ![image](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/a/7/a7bf113ce9858700671bb7159db43709dbcfc91a.png)

I lose the thread from here.

---

<div class="post-metadata">

**Author:** ![ryantrem](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ryantrem/32/34010_2.png) [@ryantrem](https://forum.babylonjs.com/u/ryantrem)\
**Post date:** [February 19, 2026, 4:55pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/12 "2026-02-19T16:55:04Z")

</div>

So in the debugger, you can get to that point where it is trying to dynamically import `pbrMaterialLoadingAdapter-gktrNUpG.js` and you never get to the next line (e.g. the promise never completes)?

If that is the case, the only way I could imagine that happening is if that bundle chunk didn’t get deployed with your webapp. Are there any errors in the console or in the network tab?

Also can you verify that file actually exists in your deployed web app? It kind of sounds like it is missing.

---

<div class="post-metadata">

**Author:** ![Corysia](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/corysia/32/50154_2.png) [@Corysia](https://forum.babylonjs.com/u/Corysia)\
**Post date:** [February 19, 2026, 6:50pm UTC](https://forum.babylonjs.com/t/gltf-loader-error-when-upgrading-to-babylonjs-8-51-2-from-8-24-0/62447/13 "2026-02-19T18:50:48Z")

</div>

That’s correct, I never get beyond that point. If I do a single step, the debugger does not pause again. I have verified that the file is there; I could see it in the browser’s list of assets. I opened it and could view the contents.

I decided to try to simplifly the problem and create a smaller sample project. And in this new project, I’m unable to replicate the issue. So, I have to conclude this is my own error somewhere in my project and not an issue with the loader.

```typescript
import "@babylonjs/inspector";
import { Scene, Engine, FreeCamera, HemisphericLight, MeshBuilder, Vector3, ImportMeshAsync } from "@babylonjs/core";
import { registerBuiltInLoaders } from "@babylonjs/loaders/dynamic";

class Main {

    constructor() {
        let canvas = document.createElement("canvas");
        canvas.style.width = '100%';
        canvas.style.height = '100%';
        document.body.appendChild(canvas);
        let engine = new Engine(canvas, true);

        registerBuiltInLoaders();

        this.initializeScene(engine, canvas);
    }

    private async initializeScene(engine: Engine, canvas: HTMLCanvasElement): Promise<void> {
        let scene = await this.createScene(engine, canvas);

        window.addEventListener("resize", function () {
            engine.resize();
        });

        window.addEventListener("keydown", (ev) => {
            // Shift+Ctrl+Alt+F
            if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.code === "KeyF") {
                engine.switchFullscreen(false);
            }
            // Shift+Ctrl+Alt+I
            if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.code === "KeyI") {
                if (scene.debugLayer.isVisible()) {
                    scene.debugLayer.hide();
                } else {
                    scene.debugLayer.show();
                }
            }
        });
        engine.runRenderLoop(function () {
            scene.render();
        })
    }

    public async createScene(engine: Engine, canvas: HTMLCanvasElement): Promise<Scene> {
        // This creates a basic Babylon Scene object (non-mesh)
        let scene = new Scene(engine);

        // This creates and positions a free camera (non-mesh)
        let camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);

        // This targets the camera to scene origin
        camera.setTarget(Vector3.Zero());

        // This attaches the camera to the canvas
        camera.attachControl(canvas, true);

        // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
        let light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);

        // Default intensity is 1. Let's dim the light a small amount
        light.intensity = 0.7;

        console.log('Loading model...');
        let result = await ImportMeshAsync('./models/PlayerVisual.glb', scene);
        console.log(`Loaded ${result.meshes.length} meshes`);
        const PlayerVisual = result.meshes[0];
        PlayerVisual.position = Vector3.Zero();
        PlayerVisual.rotation = Vector3.Zero();

        // Our built-in 'ground' shape. Params: name, options, scene
        let ground = MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);
        console.log(`Created ground: ${ground.name}`);

        return scene;
    }
}

new Main();

```

Thank you for taking the time to look.
