How to Handle Three.js Asset Loading Errors
When building 3D applications with Three.js, failed asset loads can
break the user experience or leave users staring at a blank canvas. This
article explains how to intercept loading errors using Three.js loaders
and the LoadingManager, and outlines practical strategies
for displaying fallback 3D graphics and textures when assets fail to
load.
Using LoadingManager for Global Error Handling
The THREE.LoadingManager is the most efficient way to
monitor all loading events globally. It tracks the progress of all
loaders assigned to it and triggers a central error callback if any
asset fails to load.
import * as THREE from 'three';
// Create a loading manager
const loadingManager = new THREE.LoadingManager();
// Triggered when all assets are loaded
loadingManager.onLoad = () => {
console.log('All assets loaded successfully.');
};
// Triggered when an error occurs during loading
loadingManager.onError = (url) => {
console.error(`There was an error loading: ${url}`);
// Trigger global fallback state here (e.g., UI notifications)
};
// Pass the manager to your loaders
const textureLoader = new THREE.TextureLoader(loadingManager);
const gltfLoader = new GLTFLoader(loadingManager);Handling Errors on Individual Loaders
If you need specific fallbacks for individual assets, use the error
callback parameter within the .load() method of your
specific loader. The standard signature for .load() is:
load( url, onLoad, onProgress, onError )
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
'path/to/texture.jpg',
(texture) => {
// Success: Apply texture to material
material.map = texture;
material.needsUpdate = true;
},
undefined, // Progress callback (optional)
(error) => {
// Error: Load fallback texture instead
console.warn('Texture failed to load. Applying fallback.');
material.map = createFallbackTexture();
material.needsUpdate = true;
}
);Creating Fallback Graphics
When an asset fails, you should immediately substitute it with a lightweight, procedurally generated graphic so your application remains functional.
1. Generating a Fallback Texture
Instead of loading another external image file (which could also fail), generate a fallback texture dynamically using a HTML canvas or a solid color.
function createFallbackTexture() {
const canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 128;
const ctx = canvas.getContext('2d');
// Draw a placeholder pattern (e.g., a magenta and black grid)
ctx.fillStyle = '#ff00ff';
ctx.fillRect(0, 0, 128, 128);
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, 64, 64);
ctx.fillRect(64, 64, 64, 64);
const texture = new THREE.CanvasTexture(canvas);
return texture;
}2. Rendering a Fallback 3D Model
If a complex 3D model (like a GLTF/GLB file) fails to load, you should add a simple, lightweight 3D primitive to the scene in its place. This keeps the spatial layout of your scene intact and prevents application-breaking reference errors.
const scene = new THREE.Scene();
const gltfLoader = new GLTFLoader();
gltfLoader.load(
'models/spaceship.gltf',
(gltf) => {
scene.add(gltf.scene);
},
undefined,
(error) => {
console.error('Failed to load 3D model. Loading fallback geometry.');
// Create a simple wireframe box placeholder
const fallbackGeometry = new THREE.BoxGeometry(2, 2, 2);
const fallbackMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
});
const fallbackMesh = new THREE.Mesh(fallbackGeometry, fallbackMaterial);
// Position the fallback mesh where the original model was supposed to go
fallbackMesh.position.set(0, 0, 0);
scene.add(fallbackMesh);
}
);