mastra-ai/mastra · error

notification-inbox requires a threadId

Error message

notification-inbox requires a threadId

What it means

The notification-inbox tool needs a threadId to scope which inbox to read. It resolves threadId from the tool input or falls back to context?.agent?.threadId; if both are absent it throws. Thread scoping is mandatory because notifications are stored per-thread.

Source

Thrown at packages/core/src/notifications/tool.ts:99

  const message =
    delivered > 0
      ? `${delivered} notification${delivered === 1 ? '' : 's'} will now be delivered.`
      : 'No unread notifications needed delivery.';

  return { message, delivered, markedSeen, unavailable, alreadyRead };
}

export function createNotificationInboxTool({ storage }: { storage: NotificationsStorage }) {
  return createTool({
    id: 'notification-inbox',
    description:
      'Inspect and manage the current thread notification inbox. Use this to list pending notifications, read full details after a summary, mark notifications seen, dismiss, archive, or search old notifications.',
    inputSchema: notificationActionSchema,
    execute: async (input: NotificationInboxAction, context) => {
      const threadId = input.threadId ?? context?.agent?.threadId;
      if (!threadId) {
        throw new Error('notification-inbox requires a threadId');
      }

      if (input.action === 'list') {
        const listInput: ListNotificationsInput = {
          threadId,
          status: input.status,
          priority: input.priority,
          source: input.source,
          limit: input.limit,
        };
        return { notifications: await storage.listNotifications(listInput) };
      }

      if (input.action === 'search') {
        if (!input.query) throw new Error('notification-inbox search requires query');
        return {
          notifications: await storage.listNotifications({
            threadId,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass threadId explicitly in the tool input: { action: 'list', threadId: 'your-thread-id' }
  2. Ensure the agent run has an active thread (e.g. pass a threadId/resourceId in the agent generate/stream options)
  3. When calling execute directly (tests), provide a context object with agent.threadId set

Example fix

// before
const result = await inboxTool.execute({ action: 'list' });
// after
const result = await inboxTool.execute({ action: 'list', threadId: 'thread-42' });
Defensive patterns

Strategy: validation

Validate before calling

const resolvedThreadId = input.threadId ?? context?.agent?.threadId;
if (!resolvedThreadId) throw new Error('Provide threadId or run the agent within a memory thread');

Type guard

function hasThreadId(i: { threadId?: string }, ctx?: { agent?: { threadId?: string } }): i is { threadId: string } & typeof i {
  return typeof (i.threadId ?? ctx?.agent?.threadId) === 'string';
}

Try / catch

try {
  const res = await inboxTool.execute(input, context);
} catch (e) {
  if (e instanceof Error && e.message.includes('requires a threadId')) {
    return { error: 'Start a conversation thread before using the notification inbox' };
  }
  throw e;
}

Prevention

When it happens

Trigger: Invoking the notification-inbox tool from an agent run with no active thread (no memory thread started), or calling the tool's execute directly without input.threadId and no agent context.

Common situations: Agents configured without memory/threading so context.agent.threadId is undefined; programmatic tool invocation in tests without supplying threadId; running the tool in a workflow step where no agent thread exists.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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