mastra-ai/mastra · error

No active run to decline tool call for

Error message

No active run to decline tool call for

What it means

Thrown by the session's tool-call decline method when there is no active run. Declining mirrors approval: it needs a live run ID to route the decline decision through `agent.sendToolApproval`. When `this.run.getRunId()` is undefined (run never started, finished, or was reset), the library throws instead of silently dropping the decline.

Source

Thrown at packages/core/src/agent-controller/session.ts:3789

    });
  }

  /**
   * Decline a parked tool call: drive the agent to reject it. Throws when there
   * is no active run.
   */
  async declineToolCall({
    toolCallId,
    requestContext: requestContextInput,
    declineContext,
  }: {
    toolCallId?: string;
    requestContext?: RequestContext;
    declineContext?: { reason?: string; message?: string };
  }): Promise<void> {
    const runId = this.run.getRunId();
    if (!runId) {
      throw new Error('No active run to decline tool call for');
    }

    const agent = this.machinery.getAgent();
    const requestContext = await this.machinery.buildRequestContext(requestContextInput);
    const isYolo = (this.state.get() as Record<string, unknown>).yolo === true;
    const threadId = this.thread.getId();
    if (!threadId) {
      throw new Error('Cannot decline a tool call without a current thread');
    }
    const resourceId = this.identity.getResourceId();
    await agent.sendToolApproval({
      threadId,
      resourceId,
      runId,
      toolCallId,
      approved: false,
      declineContext,
      requireToolApproval: !isYolo,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify an active run exists (run ID present) before invoking decline.
  2. If the run already ended, discard the pending decline — there is nothing to decline against.
  3. Ensure the run kickoff is awaited before enabling decline UI handlers.
  4. Restart the run if the decision must be delivered, letting the tool request re-issue.

Example fix

// before
await session.declineToolCall({ toolCallId, declineContext: { reason: 'no' } });

// after
if (session.getRunId?.()) {
  await session.declineToolCall({ toolCallId, declineContext: { reason: 'no' } });
} else {
  session.clearPendingToolRequest(toolCallId);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before declining
const runId = session.getRunId?.();
if (!runId) {
  console.warn('Run inactive; dropping decline for', toolCallId);
  return;
}

Type guard

function canDecline(session: { getRunId?: () => string | undefined }): boolean {
  return typeof session.getRunId === 'function' && typeof session.getRunId() === 'string';
}

Try / catch

try {
  await session.declineToolCall({ toolCallId, declineContext });
} catch (err) {
  if (err instanceof Error && err.message === 'No active run to decline tool call for') {
    // safe to ignore: nothing to decline against
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the decline-tool-call method (with optional toolCallId, requestContext, declineContext) before a run starts, after it completes, or after cancellation so `this.run.getRunId()` returns undefined.

Common situations: User clicking 'Decline' after the agent run already terminated; duplicate decline handlers firing post-run; decline UI rendered from stale state after a session reset.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/d23c8d17f5c30465. Report an issue: GitHub.