{"record":{"id":"455426a91511dca5","repo":"mrdoob/three.js","slug":"three-renderer-hasfeature-called-before-the-ba","errorCode":null,"errorMessage":"THREE.Renderer: .hasFeature() called before the backend is initialized. Use \"await renderer.init();\" before using this method.","messagePattern":"THREE\\.Renderer: \\.hasFeature\\(\\) 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":3041,"sourceCode":"\n\t\tif ( this._initialized === false ) await this.init();\n\n\t\treturn this.backend.resolveTimestampsAsync( type );\n\n\t}\n\n\t/**\n\t * Checks if the given feature is supported by the selected backend. If the\n\t * renderer has not been initialized, this method always returns `false`.\n\t *\n\t * @param {string} name - The feature's name.\n\t * @return {boolean} Whether the feature is supported or not.\n\t */\n\thasFeature( name ) {\n\n\t\tif ( this._initialized === false ) {\n\n\t\t\tthrow new Error( 'THREE.Renderer: .hasFeature() called before the backend is initialized. Use \"await renderer.init();\" before using this method.' );\n\n\t\t}\n\n\t\treturn this.backend.hasFeature( name );\n\n\t}\n\n\t/**\n\t * Returns `true` when the renderer has been initialized.\n\t *\n\t * @return {boolean} Whether the renderer has been initialized or not.\n\t */\n\thasInitialized() {\n\n\t\treturn this._initialized;\n\n\t}\n","sourceCodeStart":3023,"sourceCodeEnd":3059,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/src/renderers/common/Renderer.js#L3023-L3059","documentation":"Thrown by Renderer.hasFeature() when the renderer's backend has not yet been initialized. The WebGPU/WebGL backend (adapter, device, GL context) is created lazily during renderer.init(), which is async; calling hasFeature() before that point has no backend to query. The library throws rather than silently returning false so callers fail loudly on a missing await.","triggerScenarios":"Calling renderer.hasFeature('float32-blendable') (or any GPUFeatureName) on a freshly constructed WebGPURenderer / Renderer without first awaiting renderer.init(). Common in module-top-level code, app bootstrap, or capability checks done synchronously after `new WebGPURenderer()`.","commonSituations":"Upgrading from a three.js version where the backend initialized synchronously in the constructor (pre-r181 async-init change). Copying examples that omit `await renderer.init()`. Doing feature detection at the top of a module before the async init promise has resolved.","solutions":["Add `await renderer.init();` immediately after constructing the renderer, before any hasFeature/initTexture/render call.","Use the deprecated async wrapper `await renderer.hasFeatureAsync(name)` which inits internally (will emit a deprecation warning).","Guard the call with `if (renderer.hasInitialized()) { renderer.hasFeature(name) }` and otherwise defer the check until after init resolves.","Run your feature check inside the same async scope that renders the first frame, so init has already been triggered by render/compute."],"exampleFix":"// before\nconst renderer = new WebGPURenderer();\nif (renderer.hasFeature('float32-blendable')) { /* ... */ } // throws\n\n// after\nconst renderer = new WebGPURenderer();\nawait renderer.init();\nif (renderer.hasFeature('float32-blendable')) { /* ... */ }","handlingStrategy":"validation","validationCode":"async function ensureInit(renderer) {\n  if (!renderer.hasInitialized()) await renderer.init();\n}\n// usage:\nawait ensureInit(renderer);\nif (renderer.hasFeature('float32-blendable')) { /* ... */ }","typeGuard":"function canQueryFeatures(renderer) {\n  return typeof renderer.hasInitialized === 'function' && renderer.hasInitialized() === true;\n}","tryCatchPattern":"try {\n  if (renderer.hasFeature(name)) { /* path A */ }\n} catch (e) {\n  if (/hasFeature\\(\\) called before/.test(e.message)) { await renderer.init(); /* retry */ }\n  else throw e;\n}","preventionTips":["Centralize renderer construction in an async factory that awaits renderer.init() before returning the renderer.","Always treat `new WebGPURenderer()` as incomplete; pair every construction with an awaited init.","Grep your codebase for `.hasFeature(` and ensure each call site is preceded by an awaited init."],"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"}