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

  1. Assign task.func = (context) => { ... } before building/recording the frame graph.
  2. Remove the task from the graph if no custom execution is needed.
  3. 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

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


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/447a7f110378ba35. Report an issue: GitHub.