{"record":{"id":"1d23e10e8985acce","repo":"mrdoob/three.js","slug":"three-renderer-hascompatibility-called-before","errorCode":null,"errorMessage":"THREE.Renderer: .hasCompatibility() called before the backend is initialized. Use \"await renderer.init();\" before using this method.","messagePattern":"THREE\\.Renderer: \\.hasCompatibility\\(\\) called before the backend is initialized\\. Use \"await renderer\\.init\\(\\);\" before using this method\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderers/common/Renderer.js","lineNumber":3835,"sourceCode":"\t\tthis._currentSourceMaterial = previousSourceMaterial;\n\n\t\t//\n\n\t\tobject.onAfterRender( this, scene, camera, geometry, material, group );\n\n\t}\n\n\t/**\n\t * Checks if the given compatibility is supported by the selected backend.\n\t *\n\t * @param {string} name - The compatibility's name.\n\t * @return {boolean} Whether the compatibility is supported or not.\n\t */\n\thasCompatibility( name ) {\n\n\t\tif ( this._initialized === false ) {\n\n\t\t\tthrow new Error( 'THREE.Renderer: .hasCompatibility() called before the backend is initialized. Use \"await renderer.init();\" before using this method.' );\n\n\t\t}\n\n\t\treturn this.backend.hasCompatibility( name );\n\n\t}\n\n\t/**\n\t * This method represents the default `_handleObjectFunction` implementation which creates\n\t * a render object from the given data and performs the draw command with the selected backend.\n\t *\n\t * @private\n\t * @param {Object3D} object - The 3D object.\n\t * @param {Material} material - The object's material.\n\t * @param {Scene} scene - The scene the 3D object belongs to.\n\t * @param {Camera} camera - The camera the object should be rendered with.\n\t * @param {LightsNode} lightsNode - The current lights node.\n\t * @param {?{start: number, count: number}} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`.","sourceCodeStart":3817,"sourceCodeEnd":3853,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/src/renderers/common/Renderer.js#L3817-L3853","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst renderer = new WebGPURenderer();\nconst compat = renderer.hasCompatibility('storage-buffer'); // throws\n\n// after\nconst renderer = new WebGPURenderer();\nawait renderer.init();\nconst compat = renderer.hasCompatibility('storage-buffer');","handlingStrategy":"validation","validationCode":"async function safeHasCompatibility(renderer, name) {\n  if (!renderer.hasInitialized()) await renderer.init();\n  return renderer.hasCompatibility(name);\n}","typeGuard":"function rendererReady(renderer) {\n  return typeof renderer.hasInitialized === 'function' && renderer.hasInitialized();\n}","tryCatchPattern":"try {\n  return renderer.hasCompatibility(name);\n} catch (e) {\n  if (/hasCompatibility\\(\\) called before/.test(e.message)) { await renderer.init(); return renderer.hasCompatibility(name); }\n  else throw e;\n}","preventionTips":["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()."],"tags":["webgpu","lifecycle","async-init","renderer"],"backgroundTag":null,"analyzedSha":"da05705fa31f02710c19772a2aa70c7454807f0c","analyzedAt":"2026-08-12T22:51:37.160Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}