{"record":{"id":"447a7f110378ba35","repo":"BabylonJS/Babylon.js","slug":"framegraphexecutetask-execute-task-must-have-a-fu","errorCode":null,"errorMessage":"FrameGraphExecuteTask: Execute task must have a function.","messagePattern":"FrameGraphExecuteTask: Execute task must have a function\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/FrameGraph/Tasks/Misc/executeTask.ts","lineNumber":42,"sourceCode":"        return !this.customIsReady || this.customIsReady();\r\n    }\r\n\r\n    /**\r\n     * Creates a new execute task.\r\n     * @param name The name of the task.\r\n     * @param frameGraph The frame graph the task belongs to.\r\n     */\r\n    constructor(name: string, frameGraph: FrameGraph) {\r\n        super(name, frameGraph);\r\n    }\r\n\r\n    public override getClassName(): string {\r\n        return \"FrameGraphExecuteTask\";\r\n    }\r\n\r\n    public record(): FrameGraphPass<FrameGraphContext> {\r\n        if (!this.func) {\r\n            throw new Error(\"FrameGraphExecuteTask: Execute task must have a function.\");\r\n        }\r\n\r\n        const pass = this._frameGraph.addPass(this.name);\r\n\r\n        pass.setExecuteFunc((context) => {\r\n            this.func(context);\r\n        });\r\n\r\n        const passDisabled = this._frameGraph.addPass(this.name + \"_disabled\", true);\r\n\r\n        passDisabled.setExecuteFunc((context) => {\r\n            this.funcDisabled?.(context);\r\n        });\r\n\r\n        return pass;\r\n    }\r\n}\r\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/FrameGraph/Tasks/Misc/executeTask.ts#L24-L60","documentation":"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.","triggerScenarios":"Creating a FrameGraphExecuteTask and calling record() (or building the graph) without setting task.func to a (context) => void function.","commonSituations":"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.","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."],"exampleFix":"// before\nconst exec = new FrameGraphExecuteTask(\"exec\", context);\ncontext.build();\n// after\nconst exec = new FrameGraphExecuteTask(\"exec\", context);\nexec.func = (ctx) => { /* custom pass work */ };\ncontext.build();","handlingStrategy":"validation","validationCode":"if (typeof execTask.func !== \"function\") {\n  throw new Error(\"ExecuteTask.func must be assigned before building\");\n}","typeGuard":"function hasExecuteFunc(task: FrameGraphExecuteTask): task is FrameGraphExecuteTask & { func: (context: FrameGraphContext) => void } {\n  return typeof task.func === \"function\";\n}","tryCatchPattern":"try {\n  execTask.record();\n} catch (e) {\n  if (String(e).includes(\"must have a function\")) {\n    execTask.func = (context) => { /* default no-op or logging */ };\n  } else throw e;\n}","preventionTips":["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."],"tags":["frame-graph","callback","validation"],"backgroundTag":"callback-required","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}