mrdoob/three.js · error · Error
THREE.TSL: Node element ${ name } is not a function
Error message
THREE.TSL: Node element ${ name } is not a function What it means
Thrown by TSLCore.addMethodChaining() when registering a TSL method whose `nodeElement` is not a function. This is an internal registration API used to wire method chaining onto Node.prototype. A non-function value (undefined, an object, a string) means the chaining call `nodeElement(...)` would fail, so it is rejected upfront.
Source
Thrown at src/nodes/tsl/TSLCore.js:31
let currentStack = null;
const NodeElements = new Map();
// Extend Node Class for TSL using prototype
export function addMethodChaining( name, nodeElement ) {
// No require StackTrace because this is internal API
if ( NodeElements.has( name ) ) {
warn( `TSL: Redefinition of method chaining '${ name }'.` );
return;
}
if ( typeof nodeElement !== 'function' ) throw new Error( `THREE.TSL: Node element ${ name } is not a function` );
NodeElements.set( name, nodeElement );
if ( name !== 'assign' ) {
// Changing Node prototype to add method chaining
Node.prototype[ name ] = function ( ...params ) {
//if ( name === 'toVarIntent' ) return this;
return this.isStackNode ? this.addToStack( nodeElement( ...params ) ) : nodeElement( this, ...params );
};
// Adding assign method chaining
Node.prototype[ name + 'Assign' ] = function ( ...params ) {View on GitHub (pinned to da05705fa3)
Solutions
- Pass a function (typically a `nodeProxy(SomeNode)` factory) as the second argument.
- Verify the imported symbol exists and is a function before registering it.
- Check the import path and export name against the current Three.js version.
Example fix
// before
import { SomeNode } from './SomeNode.js';
addMethodChaining( 'some', SomeNode ); // SomeNode is a class, not a factory
// after
import { SomeNode } from './SomeNode.js';
addMethodChaining( 'some', nodeProxy( SomeNode ) ); Defensive patterns
Strategy: type-guard
Validate before calling
function registerMethod( name, nodeElement ) {
if ( typeof nodeElement !== 'function' ) {
throw new TypeError( `Cannot register '${ name }': nodeElement is not a function` );
}
addMethodChaining( name, nodeElement );
} Type guard
const isNodeElementFactory = ( v ) => typeof v === 'function';
Prevention
- Always pass a nodeProxy(...) factory (a function) to addMethodChaining.
- Verify imports resolve to a function before registering.
- Re-check export names after Three.js upgrades.
When it happens
Trigger: A plugin/extension calling `addMethodChaining(name, value)` with an undefined import (wrong/default import), an object instead of a factory function, or a typo'd variable; a bundler tree-shaking a named export to undefined.
Common situations: Writing a TSL extension that registers custom methods; importing a node element from the wrong path so it resolves to undefined; version mismatch where an export was renamed or removed.
Related errors
- THREE.TSL: `texture( value )` function expects a valid insta
- THREE.IndexNode: Unknown scope: ${scope}
- THREE.TSL: No "ConstNode" found in node graph.
- THREE.FunctionNode: Function is not a GLSL code.
- THREE.FunctionOverloadingNode: FunctionNode must be a layout
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/d88f242a2706a449.
Report an issue: GitHub.