Gltf file loaded twice when loading is initiated in LoadingManager() inside onProgress callback

I have two glb files, loadingScene.glb and mainScene.glb. The loadingScene.glb file consists of three meshes- text, a plane(to receive shadows), and a cactus that I’m using as part of a loading screen displayed to the user, while the mainScene.glb and all of its associated assets are still loading. In order to indicate the loading progress, I wanted to have a little fun and have a shadow shift from the left to the right to suggest the current loading progress(pictured below).

Therefore, I needed the loadingScene.glb file to load first, then after, I load the mainScene.glb content. I achieved this in the THREE.LoadingManager() onProgress callback by checking for when itemUrl==="./loadingScene.glb", indicating that, that file has been loaded, then calling a loadMainScene() function which then loads the mainScene.glb. However, when I added a console.log("itemUrl", itemUrl) inside of the onProgress callback, I see ./mainScene.glb multiple times, indicating that it is loading more than once. Why is this?

import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"

const gScene = new THREE.Scene()
const canvas = document.querySelector("#c")
const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
const gRenderer = new THREE.WebGLRenderer({canvas, alpha: true, antialias: true})
gRenderer.setPixelRatio( window.devicePixelRatio );
gRenderer.setSize( window.innerWidth, window.innerHeight );
gRenderer.toneMapping = THREE.ACESFilmicToneMapping;
gRenderer.shadowMap.enabled = true
gRenderer.toneMappingExposure = 1;
gRenderer.outputEncoding = THREE.sRGBEncoding;

gCamera.position.x = 24
gCamera.position.y = 123
gCamera.position.z = 0

const loadingManager = new THREE.LoadingManager(

    () => {


    (itemUrl, itemsLoaded, itemsTotal) => 
        console.log("itemUrl", itemUrl)

        if(itemUrl === "./loadingScene.glb"){


        let loadedRatio = itemsLoaded / itemsTotal
        if(directionalLight.position.z < 30){
            directionalLight.position.set(-20, 130, -30 + (60 * loadedRatio))


const gltfLoader = new GLTFLoader(loadingManager)

function loadMainScene(){
    gltfLoader.load('./mainScene.glb', (glb) => {    

const controls = new OrbitControls(gCamera, canvas),0,0)

const directionalLight = new THREE.DirectionalLight(0xffffff, 5)
directionalLight.castShadow =  true

directionalLight.position.set(-10, 130, -30), 115,0)['left'] = -15['right'] = 15['bottom'] = -15['top'] = 15
directionalLight.shadow.mapSize.width = 1024
directionalLight.shadow.mapSize.height = 1024;

gltfLoader.load('./loadingScene.glb', (glb) => {    
        glb.scene.traverse((child) => {      
                        child.material = new THREE.ShadowMaterial()
                        child.receiveShadow = true

                    else if("saguaro")){
                        child.material =  new THREE.MeshBasicMaterial({color:0x000000})
                        child.castShadow = true
                        child.material = new THREE.MeshBasicMaterial({color:0x1a1004})
                        child.castShadow = true

window.addEventListener('resize', onWindowResize)
function onWindowResize(){
    gCamera.aspect = window.innerWidth / window.innerHeight
    gRenderer.setSize(window.innerWidth, window.innerHeight)

function render(){

When combining LoadingManager with GLTFLoader there is a non-obvious restriction. The manager tracks for each glTF assets an additional item to make sure onLoad() is correctly fired. Unfortunately, this produces an incorrect item count and a confusing progress report.

As a workaround, I suggest you are not using LoadingManager for triggering the second loading process. Instead use something like:

const gltf = await gltfLoader.loadAsync( './loadingScene.glb' );