{"record":{"id":"8611f60f1eafe0b6","repo":"mastra-ai/mastra","slug":"storage-is-required-for-tool-approval-lookups","errorCode":null,"errorMessage":"Storage is required for tool approval lookups","messagePattern":"Storage is required for tool approval lookups","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/channels/agent-channels.ts","lineNumber":571,"sourceCode":"          // because it's keyed by toolCallId and survives parallel same-tool\n          // approvals. Fall back to the persisted `pendingToolApprovals`\n          // metadata for cases where the bot restarted between card post and\n          // click (the metadata path is lossy for parallel same-tool calls\n          // since core keys those by toolName — only the latest survives).\n          let runId: string | undefined;\n          let toolName: string | undefined;\n          let toolArgs: Record<string, unknown> | undefined;\n\n          const stashed = this.pendingApprovalCards.get(toolCallId);\n          if (stashed?.runId) {\n            runId = stashed.runId;\n            toolName = stashed.toolName;\n            toolArgs = stashed.args;\n          } else {\n            const storage = mastra.getStorage();\n            const memoryStore = storage ? await storage.getStore('memory') : undefined;\n            if (!memoryStore) {\n              throw new Error('Storage is required for tool approval lookups');\n            }\n\n            const { messages } = await memoryStore.listMessages({\n              threadId: mastraThread.id,\n              perPage: 50,\n              orderBy: { field: 'createdAt', direction: 'DESC' },\n            });\n\n            for (const msg of messages) {\n              const pending = msg.content?.metadata?.pendingToolApprovals as\n                | Record<\n                    string,\n                    {\n                      toolCallId: string;\n                      runId: string;\n                      parentRunId?: string;\n                      toolName: string;\n                      args: Record<string, unknown>;","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/channels/agent-channels.ts#L553-L589","documentation":"While handling an inbound channel event that corresponds to a pending tool-approval flow, AgentChannels must look up recent thread messages in storage to recover the stashed tool call. If no storage/memory store is configured, it cannot perform this lookup and throws.","triggerScenarios":"A channel message resolves to an approval flow path where the stashed tool call is not found in memory, so the code falls back to storage; mastra.getStorage() returns undefined or getStore('memory') returns undefined at that moment.","commonSituations":"Channels deployed without storage configuration but with tool-approval workflows enabled; dev environment using in-memory setup that reaches the approval path in production traffic.","solutions":["Configure storage with a memory store on the Mastra instance (e.g. LibSQLStore)","Use the stashed tool-call path (provide whatever state stash the approval flow expects) so the storage lookup is not needed","Disable/avoid tool approval flows in channels until storage is configured"],"exampleFix":"// before\nnew Mastra({ agents: { agent } }); // channels + tool approvals need storage\n// after\nnew Mastra({ agents: { agent }, storage: new LibSQLStore({ url: 'file:./mastra.db' }) });","handlingStrategy":"validation","validationCode":"const storage = mastra.getStorage();\nif (!storage || !(await storage.getStore('memory'))) {\n  throw new Error('Tool approval flows in channels require storage with a memory store');\n}","typeGuard":"function isStorageWithMemory(s: unknown): s is StorageType {\n  return !!s && typeof (s as StorageType).getStore === 'function';\n}","tryCatchPattern":"try {\n  await handleApprovalEvent(event);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Storage is required for tool approval')) {\n    logger.error('Enable storage before using tool approvals in channels');\n  } else throw err;\n}","preventionTips":["Provision storage before enabling tool-approval features","Smoke-test the approval path in dev with real storage","Document the storage requirement wherever approvals are configured"],"tags":["storage","channels","tool-approval"],"backgroundTag":"missing-storage-configuration","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}