{"record":{"id":"1c2cd617b8b65815","repo":"mrdoob/three.js","slug":"three-renderer-compute-expects-a-computenode","errorCode":null,"errorMessage":"THREE.Renderer: .compute() expects a ComputeNode.","messagePattern":"THREE\\.Renderer: \\.compute\\(\\) expects a ComputeNode\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderers/common/Renderer.js","lineNumber":2927,"sourceCode":"\n\t\t//\n\n\t\tthis.backend.updateTimeStampUID( computeNodes );\n\n\t\tthis.inspector.beginCompute( this.backend.getTimestampUID( computeNodes ), computeNodes );\n\n\t\t//\n\n\t\tconst backend = this.backend;\n\t\tconst pipelines = this._pipelines;\n\t\tconst bindings = this._bindings;\n\t\tconst nodes = this._nodes;\n\n\t\tconst computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];\n\n\t\tif ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) {\n\n\t\t\tthrow new Error( 'THREE.Renderer: .compute() expects a ComputeNode.' );\n\n\t\t}\n\n\t\tbackend.beginCompute( computeNodes );\n\n\t\tfor ( const computeNode of computeList ) {\n\n\t\t\t// onInit\n\n\t\t\tif ( pipelines.has( computeNode ) === false ) {\n\n\t\t\t\tconst dispose = () => {\n\n\t\t\t\t\tcomputeNode.removeEventListener( 'dispose', dispose );\n\n\t\t\t\t\tpipelines.delete( computeNode );\n\t\t\t\t\tbindings.deleteForCompute( computeNode );\n\t\t\t\t\tnodes.delete( computeNode );","sourceCodeStart":2909,"sourceCodeEnd":2945,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/src/renderers/common/Renderer.js#L2909-L2945","documentation":"Thrown by Renderer.compute() when the computeNodes argument is not a ComputeNode. Like compileComputeAsync, compute() accepts a single ComputeNode or an array, but the synchronous compute() path only checks the first element (computeList[0]); if it is undefined or lacks isComputeNode === true, the call is rejected.","triggerScenarios":"Passing undefined, null, a material, a plain object, or an empty/non-ComputeNode first element to renderer.compute(). Submitting compute work before the node was constructed.","commonSituations":"Calling compute() with a variable that was conditionally assigned and is undefined; passing a compute pipeline/binding object instead of the ComputeNode; TSL/WGSL migration where the node constructor differs.","solutions":["Build a proper ComputeNode (e.g. via TSL Fn(...).compute(count) or new THREE.ComputeNode) and pass that.","Guard: if (node && node.isComputeNode) renderer.compute(node);","When passing an array, ensure the first element is a valid ComputeNode (filter first).","Check that async node construction completed before calling compute."],"exampleFix":"// before\nrenderer.compute( computeKernel ); // not a ComputeNode\n\n// after\nconst computeNode = Fn( () => { /* ... */ } ).compute( count );\nrenderer.compute( computeNode );","handlingStrategy":"type-guard","validationCode":"const list = ( Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ] )\n  .filter( n => n && n.isComputeNode === true );\nif ( list.length && isComputeNode( list[ 0 ] ) ) renderer.compute( list );","typeGuard":"function isComputeNode( node ) {\n  return node != null && node.isComputeNode === true;\n}","tryCatchPattern":null,"preventionTips":["Build ComputeNodes via TSL Fn(...).compute(count) or new THREE.ComputeNode.","Guard compute() with node && node.isComputeNode.","Ensure the first array element is a valid ComputeNode (filter first).","Confirm async node construction finished before calling compute."],"tags":["renderer","compute","nodes","type-guard","webgpu"],"backgroundTag":null,"analyzedSha":"da05705fa31f02710c19772a2aa70c7454807f0c","analyzedAt":"2026-08-12T22:51:37.160Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}