Three.js GLB Not Loading? Common Causes and Fixes
When a GLB does not load in Three.js, the problem is not always Three.js. The file may be incomplete, compressed without a decoder, served with the wrong path, blocked by CORS, or simply too large for the browser environment.
Start by separating asset problems from runtime problems. Open the same file in a browser-local 3D model viewer. If it fails there too, inspect the asset first. If it works in the viewer but fails in your app, the problem is probably loader configuration, deployment, or rendering setup.
1. The Path Is Wrong
This is the simplest cause. The model path works in development but fails after deployment because the file moved, the base path changed, or the asset was not copied to the public directory.
Check the browser Network panel:
- Is the
.glbor.gltfrequest returning200? - Is it returning HTML instead of a model file?
- Did the path change after export or static hosting?
- Is the file blocked by redirects or authentication?
If the request does not return the model bytes, fix deployment before debugging materials or lights.
2. The glTF File References Missing Resources
A .gltf file can reference external .bin files and textures. The JSON file may load, but the model will still fail or appear incomplete if those resources are missing.
If you want simple web delivery, export a self-contained GLB. If you need folder-based glTF, deploy every referenced file and preserve relative paths.
3. Draco or meshopt Decoder Is Missing
Compressed glTF assets require decoder support. Three.js GLTFLoader supports the glTF format, but compressed extensions need the matching setup. The Three.js GLTFLoader documentation lists supported extensions and related loader configuration.
If an uncompressed GLB loads but a compressed GLB fails, check:
DRACOLoaderpath and decoder files- meshopt decoder setup
- whether the decoder files are deployed
- whether the server can serve WASM or JS decoder assets
- whether the compressed extension is supported by your target runtime
Compression is only useful if the viewer can decode it.
4. CORS or MIME Type Issues
If the model is hosted on a different domain, CORS headers must allow the browser to request it. Textures, binary buffers, and decoder files may need the same treatment.
MIME type can also matter. Static hosts usually handle .glb correctly, but custom hosting may serve it as generic text or HTML. Check response headers when the loader reports a parse failure that does not match the file.
5. The Model Loads but Is Not Visible
Sometimes the GLB loads successfully but you see a blank canvas. That can be a scene setup issue:
- camera is not aimed at the model
- model scale is extremely small or large
- model origin is far from visible geometry
- lights are missing or too weak
- material is transparent or black under the lighting
- near or far clipping plane hides the model
Use bounding box helpers or auto-fit the camera to the loaded scene. If the model appears after zooming far out, the problem is scale or origin.
6. Browser Memory or GPU Limits
A model can be valid and still too heavy. Large textures, high geometry counts, and many meshes can cause the tab to freeze or the WebGL context to fail. This is more common on mobile devices and older laptops.
Inspect file size, triangle count, vertex count, and texture budget. If the model is too large, use the 3D Model Compressor to create a lighter test version, then compare loading behavior.
Debugging Order
- Test the file in a known viewer.
- Check the Network panel for failed requests.
- Confirm
.gltfexternal resources are present. - Check Draco or meshopt decoder setup.
- Inspect CORS and response headers.
- Auto-fit the camera to model bounds.
- Test a smaller or uncompressed version.
Quick Answer
If a GLB does not load in Three.js, first test whether the file itself opens in another viewer. Then check URL paths, missing .gltf resources, Draco or meshopt decoder setup, CORS, MIME types, camera framing, scale, and browser memory limits. Most failures come from deployment or asset assumptions rather than the rendering loop itself.
Ready to try it yourself?
Put what you have learned into practice with our free online tool.
Test the Model First