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
- Define each overload as a typed/layout Fn with an explicit parameter layout (e.g. via GLSL/TSL declaration with typed inputs).
- Do not pass anonymous inline Fns to FunctionOverloadingNode; ensure every variant has a resolvable layout.
- 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
- Define every overload as a typed/layout Fn.
- Do not pass anonymous inline Fns to FunctionOverloadingNode.
- Confirm each Fn's layout generated before building the overload set.
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
- THREE.FunctionNode: Function is not a GLSL code.
- THREE.TSL: `texture( value )` function expects a valid insta
- THREE.IndexNode: Unknown scope: ${scope}
- THREE.TSL: No "ConstNode" found in node graph.
- THREE.TSL: Node element ${ name } is not a function
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/307951f37972434b.
Report an issue: GitHub.