Handle Asset Loading Errors with Three.js LoadingManager
Managing asset loading in Three.js is crucial for creating seamless
3D web experiences. This article explains how to use the
THREE.LoadingManager class, specifically focusing on its
onError callback, to intercept, identify, and handle
individual asset loading errors effectively.
Understanding the LoadingManager
In Three.js, LoadingManager handles and keeps track of
loaded and pending data. When you load multiple assets—such as textures,
3D models, or audio files—passing a shared LoadingManager
instance to your loaders allows you to monitor global loading progress,
completion, and failures.
The onError callback of the LoadingManager
triggers whenever any loader associated with that manager encounters an
error (for example, a 404 Not Found error or a corrupted file).
Implementing the onError Callback
To intercept asset-specific errors, define the onError
function on your LoadingManager instance. This callback
receives the URL of the asset that failed to load as its argument.
Here is a practical implementation:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
// 1. Initialize the LoadingManager
const loadingManager = new THREE.LoadingManager();
// 2. Define the onError callback
loadingManager.onError = function ( url ) {
console.warn( `Error loading asset: ${url}` );
handleSpecificError( url );
};
// 3. Pass the manager to your loaders
const textureLoader = new THREE.TextureLoader( loadingManager );
const gltfLoader = new GLTFLoader( loadingManager );
// Start loading assets
textureLoader.load( 'textures/wood_diffuse.jpg', (texture) => { /* ... */ } );
gltfLoader.load( 'models/hero_character.gltf', (gltf) => { /* ... */ } );Intercepting and Handling Specific Assets
Because the onError callback provides the
url of the failed resource, you can use conditional logic
to determine which asset failed and apply targeted recovery or fallback
strategies.
1. Providing Fallback Textures
If a non-critical texture fails to load, you can catch the error and apply a solid color or a default placeholder texture so the 3D model does not render completely black.
function handleSpecificError( url ) {
if ( url.includes( 'wood_diffuse.jpg' ) ) {
console.log( 'Falling back to default grey texture.' );
// Code to apply a default THREE.Color or a local embedded canvas texture
}
}2. Handling Critical Model Failures
If a critical asset (like the main character model or environment) fails to load, the application may become unusable. You can use the interceptor to notify the UI layer and display a user-friendly error message.
function handleSpecificError( url ) {
if ( url.endsWith( '.gltf' ) || url.endsWith( '.glb' ) ) {
// Show an error overlay to the user
const uiOverlay = document.getElementById( 'error-overlay' );
if ( uiOverlay ) {
uiOverlay.innerText = 'Failed to load 3D models. Please refresh the page.';
uiOverlay.style.display = 'block';
}
}
}3. Implementing Retry Logic
You can also use the intercepted URL to attempt a reload of the failed asset a limited number of times before failing completely.
const retryCount = {};
function handleSpecificError( url ) {
if ( !retryCount[url] ) {
retryCount[url] = 0;
}
if ( retryCount[url] < 3 ) {
retryCount[url]++;
console.log( `Retrying load for: ${url} (Attempt ${retryCount[url]})` );
// Re-trigger the load depending on the file type
if ( url.endsWith( '.jpg' ) || url.endsWith( '.png' ) ) {
textureLoader.load( url, (texture) => { /* Success on retry */ } );
}
} else {
console.error( `Failed to load ${url} after 3 attempts.` );
}
}