mrdoob/three.js · error · Error

THREE.FunctionOverloadingNode: FunctionNode must be a layout

Error message

THREE.FunctionOverloadingNode: FunctionNode must be a layout.

What it means

Thrown by FunctionOverloadingNode.getCandidateFn() when one of the overloaded FunctionNodes has `shaderNode.layout === null`. Overload resolution reads `layout.inputs` to score candidates by parameter count and type, so every overload must be a layout-bearing (i.e. properly typed/declared) Fn. Inline/anonymous Fn without a declared layout cannot be overloaded.

Source

Thrown at src/nodes/utils/FunctionOverloadingNode.js:100

	getCandidateFn( builder ) {

		const params = this.parametersNodes;

		let candidateFn = this._candidateFn;

		if ( candidateFn === null ) {

			let bestCandidateFn = null;
			let bestScore = - 1;

			for ( const functionNode of this.functionNodes ) {

				const shaderNode = functionNode.shaderNode;
				const layout = shaderNode.layout;

				if ( layout === null ) {

					throw new Error( 'THREE.FunctionOverloadingNode: FunctionNode must be a layout.' );

				}

				const inputs = layout.inputs;

				if ( params.length === inputs.length ) {

					let currentScore = 0;

					for ( let i = 0; i < params.length; i ++ ) {

						const param = params[ i ];
						const input = inputs[ i ];

						if ( param.getNodeType( builder ) === input.type ) {

							currentScore ++;

View on GitHub (pinned to da05705fa3)

Solutions

  1. Define each overload as a typed/layout Fn with an explicit parameter layout (e.g. via GLSL/TSL declaration with typed inputs).
  2. Do not pass anonymous inline Fns to FunctionOverloadingNode; ensure every variant has a resolvable layout.
  3. Check that each Fn's layout is generated (non-null) before constructing the overloading node.
Defensive patterns

Strategy: validation

Validate before calling

function assertOverloadsHaveLayout( functionNodes ) {
  for ( const fn of functionNodes ) {
    if ( fn.shaderNode == null || fn.shaderNode.layout === null ) {
      throw new Error( 'Every overload Fn must have a non-null layout' );
    }
  }
}

Type guard

const overloadHasLayout = ( fn ) => fn?.shaderNode?.layout != null;

Prevention

When it happens

Trigger: Passing an inline `Fn(() => {...})` (no layout) as one of the overloads to the overloading node; mixing a layout Fn with non-layout Fns; a Fn whose layout failed to generate because its signature could not be inferred.

Common situations: Building overloaded shader functions where some variants are written as compact arrow Fns; using `Fn` with a body that does not declare typed inputs; version change where layout inference became stricter.

Related errors


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