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
- Use one of the exported immutable TSL objects (vertexIndex, instanceIndex, drawIndex, invocationLocalIndex, invocationSubgroupIndex, subgroupIndex) instead of constructing IndexNode manually.
- If you must construct it, pass an IndexNode static constant, e.g. `new IndexNode(IndexNode.VERTEX)`.
- 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
- Prefer the exported TSL singletons (vertexIndex, instanceIndex, etc.) over manual construction.
- If constructing, pass IndexNode static constants, never string literals.
- Check scope names against the current Three.js version after upgrades.
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
- THREE.TSL: `texture( value )` function expects a valid insta
- THREE.TSL: No "ConstNode" found in node graph.
- THREE.FunctionNode: Function is not a GLSL code.
- THREE.TSL: Node element ${ name } is not a function
- THREE.FunctionOverloadingNode: FunctionNode must be a layout
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/cb0a110482ccdec4.
Report an issue: GitHub.