mrdoob/three.js · error

THREE.IndexNode: Unknown scope: ${scope}

Error message

THREE.IndexNode: Unknown scope: ${scope}

What it means

Thrown by IndexNode.generate() when the node's `scope` does not match any of the defined IndexNode static scopes. Valid scopes are 'vertex', 'instance', 'draw', 'invocationLocal', 'invocationSubgroup', 'subgroup'. The constructor accepts any string, so the error is deferred to build/generate time rather than construction.

Source

Thrown at src/nodes/core/IndexNode.js:86

		} else if ( scope === IndexNode.DRAW ) {

			propertyName = builder.getDrawIndex();

		} else if ( scope === IndexNode.INVOCATION_LOCAL ) {

			propertyName = builder.getInvocationLocalIndex();

		} else if ( scope === IndexNode.INVOCATION_SUBGROUP ) {

			propertyName = builder.getInvocationSubgroupIndex();

		} else if ( scope === IndexNode.SUBGROUP ) {

			propertyName = builder.getSubgroupIndex();

		} else {

			throw new Error( 'THREE.IndexNode: Unknown scope: ' + scope );

		}

		let output;

		if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) {

			output = propertyName;

		} else {

			const nodeVarying = varying( this );

			output = nodeVarying.build( builder, nodeType );

		}

		return output;

View on GitHub (pinned to da05705fa3)

Solutions

  1. Use one of the exported immutable TSL objects (vertexIndex, instanceIndex, drawIndex, invocationLocalIndex, invocationSubgroupIndex, subgroupIndex) instead of constructing IndexNode manually.
  2. If you must construct it, pass an IndexNode static constant, e.g. `new IndexNode(IndexNode.VERTEX)`.
  3. Check the scope spelling and case against the constants defined in src/nodes/core/IndexNode.js:110-115.

Example fix

// before
const idx = new IndexNode( 'invocationGlobal' );

// after
import { invocationLocalIndex } from 'three/tsl';
const idx = invocationLocalIndex;
Defensive patterns

Strategy: validation

Validate before calling

import { IndexNode } from 'three/nodes';

const VALID_SCOPES = new Set( [ 'vertex', 'instance', 'draw', 'invocationLocal', 'invocationSubgroup', 'subgroup' ] );
function assertScope( scope ) {
  if ( ! VALID_SCOPES.has( scope ) ) throw new TypeError( `Invalid IndexNode scope: ${ scope }` );
}

Type guard

const VALID_SCOPES = new Set( [ IndexNode.VERTEX, IndexNode.INSTANCE, IndexNode.DRAW, IndexNode.INVOCATION_LOCAL, IndexNode.INVOCATION_SUBGROUP, IndexNode.SUBGROUP ] );
const isValidScope = ( s ) => VALID_SCOPES.has( s );

Prevention

When it happens

Trigger: Constructing `new IndexNode('foo')` or `new IndexNode('invocationGlobal')` (a removed/renamed scope), or passing a typo like 'Vertex' (capitalized) or 'instanceIndex'. Also triggered by directly mutating `.scope` on an existing IndexNode to an invalid value.

Common situations: Using a stale scope name from an older Three.js version (e.g. the deprecated 'invocationGlobal' was renamed); passing a camelCase/wrong-case string; copy-pasting a scope literal from outdated docs; building a custom node that wraps IndexNode with a configurable scope.

Related errors


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