mrdoob/three.js · error · Error
THREE.Renderer: .hasCompatibility() called before the backen
Error message
THREE.Renderer: .hasCompatibility() called before the backend is initialized. Use "await renderer.init();" before using this method.
What it means
Thrown by Renderer.hasCompatibility() when the backend is not yet initialized. Like hasFeature(), this queries the live backend, which only exists after renderer.init() resolves. Calling it earlier has no backend to answer the query.
Source
Thrown at src/renderers/common/Renderer.js:3835
this._currentSourceMaterial = previousSourceMaterial;
//
object.onAfterRender( this, scene, camera, geometry, material, group );
}
/**
* Checks if the given compatibility is supported by the selected backend.
*
* @param {string} name - The compatibility's name.
* @return {boolean} Whether the compatibility is supported or not.
*/
hasCompatibility( name ) {
if ( this._initialized === false ) {
throw new Error( 'THREE.Renderer: .hasCompatibility() called before the backend is initialized. Use "await renderer.init();" before using this method.' );
}
return this.backend.hasCompatibility( name );
}
/**
* This method represents the default `_handleObjectFunction` implementation which creates
* a render object from the given data and performs the draw command with the selected backend.
*
* @private
* @param {Object3D} object - The 3D object.
* @param {Material} material - The object's material.
* @param {Scene} scene - The scene the 3D object belongs to.
* @param {Camera} camera - The camera the object should be rendered with.
* @param {LightsNode} lightsNode - The current lights node.
* @param {?{start: number, count: number}} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.View on GitHub (pinned to da05705fa3)
Solutions
- Call `await renderer.init();` before `renderer.hasCompatibility(name);`.
- Move the compatibility check into the post-init phase of your app bootstrap.
- Use renderer.hasInitialized() to gate the call and defer if not yet ready.
Example fix
// before
const renderer = new WebGPURenderer();
const compat = renderer.hasCompatibility('storage-buffer'); // throws
// after
const renderer = new WebGPURenderer();
await renderer.init();
const compat = renderer.hasCompatibility('storage-buffer'); Defensive patterns
Strategy: validation
Validate before calling
async function safeHasCompatibility(renderer, name) {
if (!renderer.hasInitialized()) await renderer.init();
return renderer.hasCompatibility(name);
} Type guard
function rendererReady(renderer) {
return typeof renderer.hasInitialized === 'function' && renderer.hasInitialized();
} Try / catch
try {
return renderer.hasCompatibility(name);
} catch (e) {
if (/hasCompatibility\(\) called before/.test(e.message)) { await renderer.init(); return renderer.hasCompatibility(name); }
else throw e;
} Prevention
- Defer compatibility queries until after the awaited init.
- Cache the result of compatibility checks at runtime rather than re-querying at startup.
- Gate calls with renderer.hasInitialized().
When it happens
Trigger: Calling renderer.hasCompatibility(name) on a renderer constructed but not yet initialized, e.g. to decide whether to enable a compatibility-mode code path at startup.
Common situations: Capability checks run at module load or in a constructor. Code that branches between WebGL and WebGPU compatibility paths before the first render. Migrations that previously had synchronous backend init.
Related errors
- THREE.Renderer: .hasFeature() called before the backend is i
- THREE.Renderer: .initTexture() called before the backend is
- THREE.Renderer: .initRenderTarget() called before the backen
- THREE.Renderer: .render() called before the backend is initi
- THREE.PMREMGenerator: .fromScene() called before the backend
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/1d23e10e8985acce.
Report an issue: GitHub.