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

  1. Verify the file is a valid three.js JSON scene/object (produced by toJSON() or ObjectExporter); validate it at jsonlint.com.
  2. If loading glTF/GLB, use GLTFLoader, not ObjectLoader.
  3. Check the network response body - confirm it starts with '{' and is JSON, not an HTML page.
  4. Re-export the model with scene.toJSON() and load the resulting .json.
  5. 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

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


AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12). Data as JSON: /api/errors/a46929fc4af3bfd8. Report an issue: GitHub.