{"record":{"id":"295c338497ae8db1","repo":"JuliusBrussee/caveman","slug":"withtask-a-callback-is-required","errorCode":null,"errorMessage":"withTask: a callback is required","messagePattern":"withTask: a callback is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mastra/src/index.ts","lineNumber":158,"sourceCode":"/** The task context of the currently executing async scope, if any. */\nexport function currentTask(): TaskContext | undefined {\n  return taskStorage.getStore();\n}\n\n/**\n * Runs `fn` with a task (and optional session) bound to the async scope, so the\n * span processor can stamp `caveman.task.id` / `caveman.session.id` onto every\n * Mastra span the agent or workflow produces underneath it.\n */\nexport function withTask<T>(taskId: string, fn: () => T): T;\nexport function withTask<T>(taskId: string, sessionId: string | undefined, fn: () => T): T;\nexport function withTask<T>(\n  taskId: string,\n  sessionIdOrFn: string | undefined | (() => T),\n  maybeFn?: () => T,\n): T {\n  const fn = typeof sessionIdOrFn === \"function\" ? sessionIdOrFn : maybeFn;\n  if (typeof fn !== \"function\") throw new Error(\"withTask: a callback is required\");\n  const id = requireNonEmpty(taskId, \"withTask: taskId\");\n  const sessionId = typeof sessionIdOrFn === \"function\" ? undefined : sessionIdOrFn;\n  const context: TaskContext = sessionId ? { taskId: id, sessionId } : { taskId: id };\n  return taskStorage.run(context, fn);\n}\n\n// ---------------------------------------------------------------------------\n// 3. Span processor\n// ---------------------------------------------------------------------------\n\n/** The structural slice of an OTel span this processor touches. */\nexport interface MastraSpanLike {\n  name?: string;\n  attributes?: Record<string, unknown>;\n  setAttribute?(key: string, value: string | number | boolean): unknown;\n  spanContext?(): { traceId?: string; spanId?: string };\n}\n","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/mastra/src/index.ts#L140-L176","documentation":"withTask binds a task context (and optional session) to an async scope so the Caveman span processor can stamp caveman.task.id / caveman.session.id on Mastra spans. It supports two call shapes — withTask(id, fn) and withTask(id, sessionId, fn) — and resolves the callback as 'the function-typed argument'. If neither the second nor third argument is a function (missing callback, or a second non-function arg with no third), it throws this validation error before doing anything else.","triggerScenarios":"withTask('t1') with no callback; withTask('t1', sessionId) where sessionId was passed but fn forgotten; or passing options objects in place of the callback.","commonSituations":"Refactoring from withTask(id, fn) to the session variant and dropping fn during the edit, optional-chaining a callback that is undefined (withTask(id, maybeSession, cb?.bind(x))), or TypeScript `any` masking a wrong signature at runtime.","solutions":["Pass the callback as the last argument: withTask(taskId, () => runAgent()) or withTask(taskId, sessionId, () => runAgent()).","If the session is conditional, pass `undefined` explicitly in the 3-arg form rather than omitting the callback.","Let TypeScript check the overloads — avoid annotating the call site as any."],"exampleFix":"// before\nwithTask(task.id);            // callback forgotten\n// after\nwithTask(task.id, () => myAgent.generate(prompt));\n// or with session\nwithTask(task.id, session.id, () => myAgent.generate(prompt));","handlingStrategy":"type-guard","validationCode":"// Ensure the last argument is callable before invoking\nfunction hasCallback(...args: unknown[]): boolean {\n  return typeof args[args.length - 1] === \"function\";\n}","typeGuard":"// Rely on the exported overloads; narrow at the call site\nfunction isWithTaskArgs(args: unknown[]): args is [string, () => unknown] | [string, string | undefined, () => unknown] {\n  const last = args[args.length - 1];\n  return typeof args[0] === \"string\" && typeof last === \"function\";\n}","tryCatchPattern":null,"preventionTips":["Let TypeScript's overloads type the call; avoid `any` at withTask call sites.","When adding a sessionId, add it BEFORE the callback, never instead of it.","Pass `undefined` explicitly for an absent session in the 3-arg form."],"tags":["typescript","api-misuse","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}