mastra-ai/mastra · error · MastraError
AGENT_SEND_TOOL_APPROVAL_NO_ACTIVE_THREAD_RUN
AGENT_SEND_TOOL_APPROVAL_NO_ACTIVE_THREAD_RUN
Error message
Agent "${this.name}" sendToolApproval() could not find an active or suspended run for thread "${threadId}". The run may have already completed or been resumed. What it means
Agent.sendToolApproval() first tries to resolve a runId from options; if absent, it looks up an active or suspended run for the thread (resolvedFromStorage). When neither path yields a runId, there is nothing to approve against, so it throws. The run may have finished, been resumed, or never existed for that thread.
Source
Thrown at packages/core/src/agent/agent.ts:9483
category: ErrorCategory.USER,
text:
`Agent "${this.name}" sendToolApproval() found ${matchingRuns.length} suspended runs for thread "${threadId}". ` +
`Pass a toolCallId to disambiguate, or resume a specific run with approveToolCall()/declineToolCall() and an explicit runId.`,
details: {
threadId,
resourceId,
agentName: this.name,
runIds: matchingRuns.map(run => run.runId).join(', '),
},
});
}
runId = matchingRuns[0]?.runId;
resolvedFromStorage = runId !== undefined;
}
if (!runId) {
throw new MastraError({
id: 'AGENT_SEND_TOOL_APPROVAL_NO_ACTIVE_THREAD_RUN',
domain: ErrorDomain.AGENT,
category: ErrorCategory.USER,
text:
`Agent "${this.name}" sendToolApproval() could not find an active or suspended run for thread "${threadId}". ` +
`The run may have already completed or been resumed.`,
details: {
threadId,
resourceId,
agentName: this.name,
},
});
}
const resumeOptions = deepMerge(
(streamOptions ?? {}) as Record<string, unknown>,
executionOptions as Record<string, unknown>,
) as unknown as AgentExecutionOptions<OUTPUT>;View on GitHub (pinned to 75dd419e61)
Solutions
- Re-check the thread's state: confirm there is a pending tool approval before calling sendToolApproval.
- If the run already completed, restart the conversation/turn instead of approving.
- Make the approval flow idempotent: track which approvals were already sent and skip duplicates.
- Verify threadId/resourceId correctness so the lookup targets the right thread.
Example fix
// before
await agent.sendToolApproval({ threadId }); // assumes a pending run exists
// after
const suspended = await agent.getSuspendedRuns?.({ threadId }); // or check storage
if (suspended?.length) {
await agent.sendToolApproval({ threadId, toolCallId: suspended[0].toolCalls[0].toolCallId });
} Defensive patterns
Strategy: validation
Validate before calling
const hasPending = await threadHasPendingToolApproval(threadId); // check suspended runs first if (!hasPending) return; // nothing to approve; skip silently
Try / catch
try {
await agent.sendToolApproval({ threadId, toolCallId });
} catch (e) {
if (String(e?.id) === 'AGENT_SEND_TOOL_APPROVAL_NO_ACTIVE_THREAD_RUN') {
// already completed/resumed: mark approval as stale and continue
markApprovalResolved(threadId, toolCallId);
} else throw e;
} Prevention
- Check the thread has a pending suspended run before showing the approval UI.
- Make approval submissions idempotent; disable the approve button after first submit.
- Verify threadId/resourceId correctness for the environment (dev vs prod storage).
When it happens
Trigger: Calling agent.sendToolApproval({ threadId }) with no runId/toolCallId when the thread has zero active or suspended runs — e.g. the run already completed, was already approved/resumed, or the threadId is wrong.
Common situations: Approving a tool call after the stream already finished; double-submitting an approval (first call resumed the run); approving on a thread belonging to another resource/agent; approving after a deployment restart where in-memory active runs were lost and storage holds no suspended run.
Related errors
- AGENT_SEND_TOOL_APPROVAL_AMBIGUOUS_SUSPENDED_RUNS
- AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN
- AGENT_DURABLE_METHOD_NOT_AVAILABLE
- No active run to approve tool call for
- Cannot approve a tool call without a current thread
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e8a2e912e8d63897.
Report an issue: GitHub.