mrdoob/three.js · error
THREE.ObjectLoader: Can't parse ${url}. ${e.message}
Error message
THREE.ObjectLoader: Can't parse ${url}. ${e.message} What it means
Thrown by ObjectLoader when the text loaded from url cannot be parsed by JSON.parse. This happens before any three.js structure validation - the file content is not valid JSON at all (syntax error, truncated, or non-JSON body). The original parse error message is appended for diagnosis.
Source
Thrown at src/loaders/ObjectLoader.js:183
const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
this.resourcePath = this.resourcePath || path;
const loader = new FileLoader( this.manager );
loader.setPath( this.path );
loader.setRequestHeader( this.requestHeader );
loader.setWithCredentials( this.withCredentials );
const text = await loader.loadAsync( url, onProgress );
let json;
try {
json = JSON.parse( text );
} catch ( e ) {
throw new Error( 'THREE.ObjectLoader: Can\'t parse ' + url + '. ' + e.message );
}
const metadata = json.metadata;
if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
}
return await scope.parseAsync( json );
}
/**
* Parses the given JSON. This is used internally by {@link ObjectLoader#load}
* but can also be used directly to parse a previously loaded JSON structure.View on GitHub (pinned to da05705fa3)
Solutions
- Verify the file is a valid three.js JSON scene/object (produced by toJSON() or ObjectExporter); validate it at jsonlint.com.
- If loading glTF/GLB, use GLTFLoader, not ObjectLoader.
- Check the network response body - confirm it starts with '{' and is JSON, not an HTML page.
- Re-export the model with scene.toJSON() and load the resulting .json.
- Remove JSON comments/trailing commas and ensure UTF-8 encoding without BOM.
Example fix
// before: pointing a binary/text asset at ObjectLoader
objectLoader.load('model.glb', onLoad);
// after: use the right loader, or a valid JSON export
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('model.glb', (g) => onLoad(g.scene));
// or, for a real three.js JSON scene:
objectLoader.load('scene.json', onLoad); Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeThreeJSON(text) {
const trimmed = text.trimStart();
if (!trimmed.startsWith('{')) return false;
try { JSON.parse(text); return true; } catch { return false; }
}
const text = await fetch(url).then(r => r.text());
if (!looksLikeThreeJSON(text)) throw new Error(`${url} is not valid JSON`); Type guard
function isParsableJSON(text) {
try { JSON.parse(text); return true; } catch { return false; }
} Try / catch
try {
const obj = await objectLoader.loadAsync(url);
} catch (e) {
if (/Can't parse/.test(e.message)) {
console.error(`${url} is not valid JSON - use GLTFLoader for glTF/GLB`);
}
throw e;
} Prevention
- Use GLTFLoader for .gltf/.glb, not ObjectLoader.
- Validate exported JSON with scene.toJSON() round-trips.
- Inspect the response body - an HTML page means a routing/CORS problem.
When it happens
Trigger: Calling objectLoader.load(url, onLoad) or loadAsync(url) where the server returns an HTML error page, a binary file, a .glb (binary) instead of .json, truncated JSON due to network interruption, or a JSON file with trailing commas/comments (which strict JSON.parse rejects).
Common situations: Loading a .gltf or .glb binary with ObjectLoader instead of GLTFLoader. Server returning a 200 with an HTML error/spa page. Hand-edited JSON with comments. Proxied response that injected HTML. File saved with BOM or wrong encoding.
Related errors
- THREE.ObjectLoader: Can't load ${url}
- THREE.KeyframeTrack: Unsupported typeName: ${typeName}
- THREE.KeyframeTrack: track type undefined, can not parse
- fetch for "${response.url}" responded with ${response.status
- unsupported shape type: ${type}
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/a46929fc4af3bfd8.
Report an issue: GitHub.