mastra-ai/mastra · error · HTTPException
Tool call id is required
Error message
Tool call id is required
What it means
The POST /agents/:agentId/approve-tool-call route requires a runId and toolCallId in the request body. The server validates them before resuming the agent run and throws HTTPException 400 when either is missing or empty. toolCallId identifies which pending tool invocation is being approved.
Source
Thrown at packages/server/src/server/handlers/agents.ts:2533
responseSchema: toolCallResponseSchema,
summary: 'Approve tool call',
description: 'Approves a pending tool call and continues agent execution',
tags: ['Agents', 'Tools'],
requiresAuth: true,
handler: async ({ mastra, agentId, abortSignal, requestContext, ...params }) => {
try {
const agent = await getAgentFromSystem({
mastra,
agentId,
versionOptions: extractVersionOptions(requestContext),
});
if (!params.runId) {
throw new HTTPException(400, { message: 'Run id is required' });
}
if (!params.toolCallId) {
throw new HTTPException(400, { message: 'Tool call id is required' });
}
// UI Frameworks may send "client tools" in the body,
// but it interferes with llm providers tool handling, so we remove them
sanitizeBody(params, ['tools', 'actor']);
await validateDurableToolCallAccess({
mastra,
agent,
runId: params.runId,
toolCallId: params.toolCallId,
requestContext,
});
const streamResult = await agent.approveToolCall({
...params,
requestContext,
abortSignal,View on GitHub (pinned to 75dd419e61)
Solutions
- Add toolCallId (the id of the suspended tool call, from the suspend chunk / suspended-runs response) to the request body
- Verify the body matches approveToolCallBodySchema — send JSON with at least { runId, toolCallId }
- Check the field is not an empty string; falsy values fail the check
- Update @mastra/client-js / playground UI to a version that sends toolCallId
Example fix
// before
await fetch(`/api/agents/${agentId}/approve-tool-call`, { method: 'POST', body: JSON.stringify({ runId }) });
// after
await fetch(`/api/agents/${agentId}/approve-tool-call`, { method: 'POST', body: JSON.stringify({ runId, toolCallId: pendingToolCall.id }) }); Defensive patterns
Strategy: validation
Validate before calling
if (!runId || !toolCallId) throw new Error('approve-tool-call requires runId and toolCallId'); Type guard
function hasToolCallInput(p: unknown): p is { runId: string; toolCallId: string } {
return typeof p === 'object' && p !== null && typeof (p as any).runId === 'string' && (p as any).runId.length > 0 && typeof (p as any).toolCallId === 'string' && (p as any).toolCallId.length > 0;
} Try / catch
try { await approveToolCall({ runId, toolCallId }); } catch (e) { if (e instanceof MastraClientError && e.status === 400) console.error('Missing runId/toolCallId:', e.message); else throw e; } Prevention
- Store the toolCallId from the suspend chunk when the run suspends
- Use the typed @mastra/client-js agent methods so required fields are enforced at compile time
- Validate the approval payload against the route's body schema in client-side tests
When it happens
Trigger: POST to /agents/:agentId/approve-tool-call with a body omitting toolCallId (or sending it as empty string/undefined). The runId check on the same handler passes but toolCallId is absent.
Common situations: Hand-rolled curl/fetch calls against the approve endpoint; client SDK versions built before toolCallId was required; UI code forwarding only runId after a suspend event; copying a payload from a 'decline' flow that used different field names.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Run id is required
- Vector name is required
- resourceId and threadId are required when runId is not provi
- threadId is required
- Messages should be an array
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/0d58a9dec0c0acfd.
Report an issue: GitHub.