mrdoob/three.js · error · Error

THREE.NodeLibrary: Node class ${ nodeClass.name } is not a c

Error message

THREE.NodeLibrary: Node class ${ nodeClass.name } is not a class.

What it means

Thrown by NodeLibrary.addType() when the supplied nodeClass argument is not a function (i.e. not a JS class/constructor). The library maps a type id to a Node constructor, so a non-callable value (undefined, an instance, a plain object, a number) is a programming error. Note: if nodeClass is undefined/null, reading `nodeClass.name` in the message can itself throw — pass a real class.

Source

Thrown at src/renderers/common/nodes/NodeLibrary.js:164

	}

	/**
	 * Adds a node class definition for the given type to the provided type library.
	 *
	 * @param {Node.constructor} nodeClass - The node class definition.
	 * @param {number|string} type - The object type.
	 * @param {Map<number|string,Node.constructor>} library - The type library.
	 */
	addType( nodeClass, type, library ) {

		if ( library.has( type ) ) {

			warn( `Redefinition of node ${ type }` );
			return;

		}

		if ( typeof nodeClass !== 'function' ) throw new Error( `THREE.NodeLibrary: Node class ${ nodeClass.name } is not a class.` );
		if ( typeof type === 'function' || typeof type === 'object' ) throw new Error( `THREE.NodeLibrary: Base class ${ type } is not a class.` );

		library.set( type, nodeClass );

	}

	/**
	 * Adds a node class definition for the given class definition to the provided type library.
	 *
	 * @param {Node.constructor} nodeClass - The node class definition.
	 * @param {Node.constructor} baseClass - The class definition.
	 * @param {WeakMap<Node.constructor, Node.constructor>} library - The type library.
	 */
	addClass( nodeClass, baseClass, library ) {

		if ( library.has( baseClass ) ) {

			warn( `Redefinition of node ${ baseClass.name }` );

View on GitHub (pinned to da05705fa3)

Solutions

  1. Ensure the first argument is the class itself (a function), not an instance: `addType(MyNodeClass, type, library)`.
  2. Check for failed imports — log `nodeClass` before registering; if undefined, fix the import path or circular dependency.
  3. Reorder module imports so node class modules are fully evaluated before addType is called.
  4. Mark side-effect-bearing registration modules as sideEffects: false cautiously, or import them eagerly.

Example fix

// before
import { MyNode } from './MyNode.js'; // MyNode is undefined due to circular import
library.addType(MyNode, 42, library.materialNodes); // throws

// after
// fix the circular import so MyNode is defined, then:
library.addType(MyNode, 42, library.materialNodes);
Defensive patterns

Strategy: type-guard

Validate before calling

function safeAddType(nodeClass, type, library) {
  if (typeof nodeClass !== 'function') {
    throw new TypeError(`addType expected a class, got ${typeof nodeClass}`);
  }
  library.addType(nodeClass, type, library);
}

Type guard

function isNodeClass(v) {
  return typeof v === 'function' && /^(class |function )/.test(v.toString());
}

Try / catch

try {
  library.addType(nodeClass, type, library);
} catch (e) {
  if (/Node class .* is not a class/.test(e.message)) { console.error('Registration skipped: nodeClass is', nodeClass); /* fix import then re-register */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling `nodeLibrary.addType(someValue, type, library)` where someValue is undefined (e.g. a failed import), an instance rather than a class, or a primitive. Triggered indirectly by addMaterialNode/addLightNode paths that route through addType.

Common situations: Circular import that evaluated to undefined at registration time. Passing `new MyNode()` instead of `MyNode`. Plugin/extension registration done before the node class module finished loading. Bundler tree-shaking removing a side-effect-only class export.

Related errors


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