mrdoob/three.js · error · Error

THREE.Renderer: .compute() expects a ComputeNode.

Error message

THREE.Renderer: .compute() expects a ComputeNode.

What it means

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.

Source

Thrown at src/renderers/common/Renderer.js:2927

		//

		this.backend.updateTimeStampUID( computeNodes );

		this.inspector.beginCompute( this.backend.getTimestampUID( computeNodes ), computeNodes );

		//

		const backend = this.backend;
		const pipelines = this._pipelines;
		const bindings = this._bindings;
		const nodes = this._nodes;

		const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];

		if ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) {

			throw new Error( 'THREE.Renderer: .compute() expects a ComputeNode.' );

		}

		backend.beginCompute( computeNodes );

		for ( const computeNode of computeList ) {

			// onInit

			if ( pipelines.has( computeNode ) === false ) {

				const dispose = () => {

					computeNode.removeEventListener( 'dispose', dispose );

					pipelines.delete( computeNode );
					bindings.deleteForCompute( computeNode );
					nodes.delete( computeNode );

View on GitHub (pinned to da05705fa3)

Solutions

  1. Build a proper ComputeNode (e.g. via TSL Fn(...).compute(count) or new THREE.ComputeNode) and pass that.
  2. Guard: if (node && node.isComputeNode) renderer.compute(node);
  3. When passing an array, ensure the first element is a valid ComputeNode (filter first).
  4. Check that async node construction completed before calling compute.

Example fix

// before
renderer.compute( computeKernel ); // not a ComputeNode

// after
const computeNode = Fn( () => { /* ... */ } ).compute( count );
renderer.compute( computeNode );
Defensive patterns

Strategy: type-guard

Validate before calling

const list = ( Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ] )
  .filter( n => n && n.isComputeNode === true );
if ( list.length && isComputeNode( list[ 0 ] ) ) renderer.compute( list );

Type guard

function isComputeNode( node ) {
  return node != null && node.isComputeNode === true;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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