mastra-ai/mastra · error

Storage is required for tool approval lookups

Error message

Storage is required for tool approval lookups

What it means

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.

Source

Thrown at packages/core/src/channels/agent-channels.ts:571

          // because it's keyed by toolCallId and survives parallel same-tool
          // approvals. Fall back to the persisted `pendingToolApprovals`
          // metadata for cases where the bot restarted between card post and
          // click (the metadata path is lossy for parallel same-tool calls
          // since core keys those by toolName — only the latest survives).
          let runId: string | undefined;
          let toolName: string | undefined;
          let toolArgs: Record<string, unknown> | undefined;

          const stashed = this.pendingApprovalCards.get(toolCallId);
          if (stashed?.runId) {
            runId = stashed.runId;
            toolName = stashed.toolName;
            toolArgs = stashed.args;
          } else {
            const storage = mastra.getStorage();
            const memoryStore = storage ? await storage.getStore('memory') : undefined;
            if (!memoryStore) {
              throw new Error('Storage is required for tool approval lookups');
            }

            const { messages } = await memoryStore.listMessages({
              threadId: mastraThread.id,
              perPage: 50,
              orderBy: { field: 'createdAt', direction: 'DESC' },
            });

            for (const msg of messages) {
              const pending = msg.content?.metadata?.pendingToolApprovals as
                | Record<
                    string,
                    {
                      toolCallId: string;
                      runId: string;
                      parentRunId?: string;
                      toolName: string;
                      args: Record<string, unknown>;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Configure storage with a memory store on the Mastra instance (e.g. LibSQLStore)
  2. Use the stashed tool-call path (provide whatever state stash the approval flow expects) so the storage lookup is not needed
  3. Disable/avoid tool approval flows in channels until storage is configured

Example fix

// before
new Mastra({ agents: { agent } }); // channels + tool approvals need storage
// after
new Mastra({ agents: { agent }, storage: new LibSQLStore({ url: 'file:./mastra.db' }) });
Defensive patterns

Strategy: validation

Validate before calling

const storage = mastra.getStorage();
if (!storage || !(await storage.getStore('memory'))) {
  throw new Error('Tool approval flows in channels require storage with a memory store');
}

Type guard

function isStorageWithMemory(s: unknown): s is StorageType {
  return !!s && typeof (s as StorageType).getStore === 'function';
}

Try / catch

try {
  await handleApprovalEvent(event);
} catch (err) {
  if (err instanceof Error && err.message.includes('Storage is required for tool approval')) {
    logger.error('Enable storage before using tool approvals in channels');
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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