{"record":{"id":"8168144e1d4c5249","repo":"mastra-ai/mastra","slug":"cannot-approve-a-tool-call-without-a-current-threa","errorCode":null,"errorMessage":"Cannot approve a tool call without a current thread","messagePattern":"Cannot approve a tool call without a current thread","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent-controller/session.ts","lineNumber":3757,"sourceCode":"   */\n  async approveToolCall({\n    toolCallId,\n    requestContext: requestContextInput,\n  }: {\n    toolCallId?: string;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    const runId = this.run.getRunId();\n    if (!runId) {\n      throw new Error('No active run to approve tool call for');\n    }\n\n    const agent = this.machinery.getAgent();\n    const requestContext = await this.machinery.buildRequestContext(requestContextInput);\n    const isYolo = (this.state.get() as Record<string, unknown>).yolo === true;\n    const threadId = this.thread.getId();\n    if (!threadId) {\n      throw new Error('Cannot approve a tool call without a current thread');\n    }\n    const resourceId = this.identity.getResourceId();\n    await agent.sendToolApproval({\n      threadId,\n      resourceId,\n      runId,\n      toolCallId,\n      approved: true,\n      requireToolApproval: !isYolo,\n      memory: { thread: threadId, resource: resourceId },\n      abortSignal: this.run.ensureAbortController().signal,\n      requestContext,\n      toolsets: await this.machinery.buildToolsets(requestContext),\n    });\n  }\n\n  /**\n   * Decline a parked tool call: drive the agent to reject it. Throws when there","sourceCodeStart":3739,"sourceCodeEnd":3775,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent-controller/session.ts#L3739-L3775","documentation":"Thrown when approving a tool call while the session has no current conversation thread. `agent.sendToolApproval` requires both `threadId` and `resourceId` to persist the approval decision; the session resolves the thread via `this.thread.getId()`, and when no thread has been created/selected the approval cannot be recorded, so the library throws.","triggerScenarios":"Calling the approve-tool-call method on a session where `this.thread.getId()` returns undefined — i.e., no thread was created, selected, or the thread was cleared before approving.","commonSituations":"Creating a fresh session and approving a tool call without first starting a conversation that establishes a thread; clearing/resetting thread state mid-run; multi-session apps where the approval is routed to a session that never had its thread set.","solutions":["Ensure the session has a current thread before approving — start the run normally so the thread is created, or explicitly select/create a thread.","Verify thread lifecycle code isn't clearing the current thread while a run awaiting approval is still active.","If using multiple sessions, route the approval to the session instance that owns the originating thread."],"exampleFix":"// before\nawait session.approveToolCall({ toolCallId }); // thread may be unset\n\n// after\nif (session.getCurrentThreadId?.()) {\n  await session.approveToolCall({ toolCallId });\n} else {\n  await session.selectThread(existingThreadId);\n  await session.approveToolCall({ toolCallId });\n}","handlingStrategy":"validation","validationCode":"// before approving\nconst threadId = session.getCurrentThreadId?.();\nif (!threadId) {\n  throw new Error('Select or create a thread before approving tool calls');\n}","typeGuard":"function hasThread(session: { getCurrentThreadId?: () => string | undefined }): boolean {\n  return typeof session.getCurrentThreadId === 'function' && typeof session.getCurrentThreadId() === 'string';\n}","tryCatchPattern":"try {\n  await session.approveToolCall({ toolCallId });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('without a current thread')) {\n    await session.selectThread(fallbackThreadId);\n    await session.approveToolCall({ toolCallId });\n  } else throw err;\n}","preventionTips":["Always start runs within an established thread context.","Don't clear thread state while tool approvals are pending.","Keep a single session instance per conversation to avoid routing approvals to the wrong session."],"tags":["agent","tool-approval","thread"],"backgroundTag":"missing-thread-context","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}