BabylonJS/Babylon.js · error · Error
FrameGraphExecuteTask: Execute task must have a function.
Error message
FrameGraphExecuteTask: Execute task must have a function.
What it means
FrameGraphExecuteTask is a generic task that runs a user-supplied callback inside a frame graph pass. record() throws if the task.func property was never assigned, because there is no execute function to invoke for the pass.
Source
Thrown at packages/dev/core/src/FrameGraph/Tasks/Misc/executeTask.ts:42
return !this.customIsReady || this.customIsReady();
}
/**
* Creates a new execute task.
* @param name The name of the task.
* @param frameGraph The frame graph the task belongs to.
*/
constructor(name: string, frameGraph: FrameGraph) {
super(name, frameGraph);
}
public override getClassName(): string {
return "FrameGraphExecuteTask";
}
public record(): FrameGraphPass<FrameGraphContext> {
if (!this.func) {
throw new Error("FrameGraphExecuteTask: Execute task must have a function.");
}
const pass = this._frameGraph.addPass(this.name);
pass.setExecuteFunc((context) => {
this.func(context);
});
const passDisabled = this._frameGraph.addPass(this.name + "_disabled", true);
passDisabled.setExecuteFunc((context) => {
this.funcDisabled?.(context);
});
return pass;
}
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Assign task.func = (context) => { ... } before building/recording the frame graph.
- Remove the task from the graph if no custom execution is needed.
- Guard with a check (if (task.func)) in builder code that conditionally configures execute tasks.
Example fix
// before
const exec = new FrameGraphExecuteTask("exec", context);
context.build();
// after
const exec = new FrameGraphExecuteTask("exec", context);
exec.func = (ctx) => { /* custom pass work */ };
context.build(); Defensive patterns
Strategy: validation
Validate before calling
if (typeof execTask.func !== "function") {
throw new Error("ExecuteTask.func must be assigned before building");
} Type guard
function hasExecuteFunc(task: FrameGraphExecuteTask): task is FrameGraphExecuteTask & { func: (context: FrameGraphContext) => void } {
return typeof task.func === "function";
} Try / catch
try {
execTask.record();
} catch (e) {
if (String(e).includes("must have a function")) {
execTask.func = (context) => { /* default no-op or logging */ };
} else throw e;
} Prevention
- Set func in the constructor-adjacent code so it can never be left undefined.
- Avoid creating execute tasks speculatively; create them only when the callback exists.
- Wrap task creation in a factory that enforces func assignment.
When it happens
Trigger: Creating a FrameGraphExecuteTask and calling record() (or building the graph) without setting task.func to a (context) => void function.
Common situations: Instantiating the task as a placeholder and postponing func assignment, but the graph still records it; refactoring that renamed or removed the callback assignment; conditional code paths that skip setting func.
Related errors
- FrameGraphHighlightLayerTask "${this.name}": objectRendererT
- FrameGraphSelectionOutlineLayerTask "${this.name}": depthTex
- FrameGraphCullObjectsTask ${this.name}: objectList and camer
- FrameGraphLightingVolumeTask ${this.name}: shadowGenerator i
- FrameGraphLightingVolumeTask ${this.name}: light must be a d
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/447a7f110378ba35.
Report an issue: GitHub.