mrdoob/three.js · error · Error

THREE.Renderer: .compileComputeAsync() expects a ComputeNode

Error message

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

What it means

Thrown by Renderer.compileComputeAsync() when the computeNodes argument is not a ComputeNode (or an array of them). The method accepts a single ComputeNode or an array, but every element must be a non-null object with isComputeNode === true; undefined/null/non-ComputeNode values are rejected.

Source

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

	 * phenomenon which is called "shader compilation stutter", which occurs when
	 * rendering an object with a new shader for the first time.
	 *
	 * @async
	 * @param {Node|Array<Node>} computeNodes - The compute node(s).
	 * @param {onProgressCallback} [onProgress] - Executed while the compilation is in progress.
	 * @return {Promise} A Promise that resolves when the compile has been finished.
	 */
	async compileComputeAsync( computeNodes, onProgress = null ) {

		if ( this._isDeviceLost === true ) return;

		if ( this._initialized === false ) await this.init();

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

		if ( computeList.length === 0 || computeList.some( ( computeNode ) => computeNode === undefined || computeNode === null || computeNode.isComputeNode !== true ) ) {

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

		}

		const total = computeList.length;
		let loaded = 0;

		//

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

		for ( const computeNode of computeList ) {

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

				const dispose = () => {

View on GitHub (pinned to da05705fa3)

Solutions

  1. Construct a ComputeNode via Fn/instancing or new THREE.ComputeNode(...) and pass that instance.
  2. If passing an array, filter out null/undefined first: nodes.filter(n => n && n.isComputeNode).
  3. Verify node && node.isComputeNode === true before calling compileComputeAsync.
  4. Ensure the compute node import path matches your three.js version (Nodes API changed across releases).

Example fix

// before
await renderer.compileComputeAsync( computePipeline ); // not a ComputeNode

// after
import { Fn, instanceIndex } from 'three/tsl';
const computeNode = Fn( () => { /* ... */ } ).compute( count );
await renderer.compileComputeAsync( 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 ) await renderer.compileComputeAsync( list );

Type guard

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

Prevention

When it happens

Trigger: Passing a NodeMaterial, a compute pipeline object, undefined, null, or a plain object to compileComputeAsync; passing an array that contains a null/undefined element; referencing a compute node variable that was never assigned.

Common situations: Migrating from WebGLRenderer to the WebGPU/Nodes Renderer and confusing compute node APIs; passing the result of an async initializer that resolved to undefined; array filters that leave holes.

Related errors


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