mastra-ai/mastra · error

Resource ID is required to list threads

Error message

Resource ID is required to list threads

What it means

`listThreadsForResource` lists an agent's threads and requires a `resourceId` to scope the query. If the argument is falsy (undefined, null, or empty string) it throws before touching storage, because listing threads without a resource owner would leak or return unscoped data.

Source

Thrown at packages/memory/src/tools/om-tools.ts:232

  limit = 20,
  before,
  after,
}: {
  memory: RecallMemory;
  resourceId: string;
  currentThreadId: string;
  page?: number;
  limit?: number;
  before?: string;
  after?: string;
}): Promise<{
  threads: string;
  count: number;
  page: number;
  hasMore: boolean;
}> {
  if (!resourceId) {
    throw new Error('Resource ID is required to list threads');
  }

  const MAX_LIMIT = 50;
  const normalizedLimit = Math.min(Math.max(limit, 1), MAX_LIMIT);

  const hasDateFilter = !!(before || after);
  const beforeDate = before ? new Date(before) : null;
  const afterDate = after ? new Date(after) : null;

  // When date filtering, fetch all threads and filter client-side
  // (storage layer doesn't support date range on threads)
  const result = await memory.listThreads({
    filter: { resourceId },
    page: hasDateFilter ? 0 : page,
    perPage: hasDateFilter ? false : normalizedLimit,
    orderBy: { field: 'updatedAt', direction: 'DESC' },
  });

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass the authenticated user/resource identifier explicitly: listThreadsForResource({ memory, resourceId: user.id, currentThreadId }).
  2. Resolve resourceId from your auth/session context before invoking the tool, and fail early with a friendly message if absent.
  3. If using the LLM-facing tool, keep resourceId out of the model's hands — inject it server-side via the tool's execute closure.

Example fix

// before
await listThreadsForResource({ memory, resourceId: session?.userId, currentThreadId });
// after
if (!session?.userId) {
  throw new Error('Sign in before listing threads.');
}
await listThreadsForResource({ memory, resourceId: session.userId, currentThreadId });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof resourceId !== 'string' || resourceId.trim() === '') {
  throw new Error('resourceId is required to list threads.');
}
await listThreadsForResource({ memory, resourceId, currentThreadId });

Type guard

function hasResourceId(args: { resourceId?: string | null }): args is { resourceId: string } {
  return typeof args.resourceId === 'string' && args.resourceId.trim().length > 0;
}

Try / catch

try {
  return await listThreadsForResource({ memory, resourceId, currentThreadId });
} catch (e) {
  if (e instanceof Error && e.message.includes('Resource ID is required')) {
    return { threads: '[]', count: 0, page: 0, hasMore: false }; // or prompt for sign-in
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling listThreadsForResource with resourceId omitted, or passing an empty string from an uninitialized user/session variable; wiring the om listThreads tool without a resourceId resolver so it defaults to ''. Called by result/page1/page2/recallTool paths.

Common situations: Auth context not yet resolved when the tool runs (user id undefined); agent config missing the resourceId wiring; a migration where resourceId was optional in an older API version and is now mandatory.

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/47bd36ed49237d8f. Report an issue: GitHub.