JuliusBrussee/caveman · error
withTask: a callback is required
Error message
withTask: a callback is required
What it means
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.
Source
Thrown at packages/mastra/src/index.ts:158
/** The task context of the currently executing async scope, if any. */
export function currentTask(): TaskContext | undefined {
return taskStorage.getStore();
}
/**
* Runs `fn` with a task (and optional session) bound to the async scope, so the
* span processor can stamp `caveman.task.id` / `caveman.session.id` onto every
* Mastra span the agent or workflow produces underneath it.
*/
export function withTask<T>(taskId: string, fn: () => T): T;
export function withTask<T>(taskId: string, sessionId: string | undefined, fn: () => T): T;
export function withTask<T>(
taskId: string,
sessionIdOrFn: string | undefined | (() => T),
maybeFn?: () => T,
): T {
const fn = typeof sessionIdOrFn === "function" ? sessionIdOrFn : maybeFn;
if (typeof fn !== "function") throw new Error("withTask: a callback is required");
const id = requireNonEmpty(taskId, "withTask: taskId");
const sessionId = typeof sessionIdOrFn === "function" ? undefined : sessionIdOrFn;
const context: TaskContext = sessionId ? { taskId: id, sessionId } : { taskId: id };
return taskStorage.run(context, fn);
}
// ---------------------------------------------------------------------------
// 3. Span processor
// ---------------------------------------------------------------------------
/** The structural slice of an OTel span this processor touches. */
export interface MastraSpanLike {
name?: string;
attributes?: Record<string, unknown>;
setAttribute?(key: string, value: string | number | boolean): unknown;
spanContext?(): { traceId?: string; spanId?: string };
}
View on GitHub (pinned to 27d5a3981a)
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.
Example fix
// before withTask(task.id); // callback forgotten // after withTask(task.id, () => myAgent.generate(prompt)); // or with session withTask(task.id, session.id, () => myAgent.generate(prompt));
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the last argument is callable before invoking
function hasCallback(...args: unknown[]): boolean {
return typeof args[args.length - 1] === "function";
} Type guard
// Rely on the exported overloads; narrow at the call site
function isWithTaskArgs(args: unknown[]): args is [string, () => unknown] | [string, string | undefined, () => unknown] {
const last = args[args.length - 1];
return typeof args[0] === "string" && typeof last === "function";
} Prevention
- 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.
When it happens
Trigger: withTask('t1') with no callback; withTask('t1', sessionId) where sessionId was passed but fn forgotten; or passing options objects in place of the callback.
Common situations: 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.
Related errors
- caveman agent: file path is required
- caveman agent: unknown tool effect ${JSON.stringify(options.
- cave_breaker_threshold_invalid
- caveman agent: subagent maxCalls must be a positive integer
- caveman agent: invalid tool name ${JSON.stringify(options.na
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/295c338497ae8db1.
Report an issue: GitHub.