mastra-ai/mastra · error · HTTPException

Both threadId or resourceId must be provided

Error message

Both threadId or resourceId must be provided

What it means

Thrown by the deprecated POST /agents/:agentId/generate-legacy route handler when exactly one of threadId/resourceId is provided. Memory-scoped generation requires both together: threadId identifies the conversation thread and resourceId identifies its owning resource, so a lone value is rejected with 400.

Source

Thrown at packages/server/src/server/handlers/agents.ts:1508

        requestContext,
      });

      // UI Frameworks may send "client tools" in the body,
      // but it interferes with llm providers tool handling, so we remove them
      sanitizeBody(params, ['tools', 'actor']);

      const { messages, resourceId, resourceid, threadId, ...rest } = params;
      // Use resourceId if provided, fall back to resourceid (deprecated)
      const clientResourceId = resourceId ?? resourceid;

      // Authorization: context values take precedence over client-provided values
      const effectiveResourceId = getEffectiveResourceId(requestContext, clientResourceId);
      const effectiveThreadId = getEffectiveThreadId(requestContext, threadId);

      validateBody({ messages });

      if ((effectiveThreadId && !effectiveResourceId) || (!effectiveThreadId && effectiveResourceId)) {
        throw new HTTPException(400, { message: 'Both threadId or resourceId must be provided' });
      }

      // Validate thread ownership if accessing an existing thread
      if (effectiveThreadId) {
        const memory = await agent.getMemory({ requestContext });
        if (memory) {
          const thread = await memory.getThreadById({ threadId: effectiveThreadId });
          if (thread) {
            await enforceThreadAccess({
              mastra,
              requestContext,
              threadId: effectiveThreadId,
              thread,
              effectiveResourceId,
              permission: MastraFGAPermissions.MEMORY_WRITE,
            });
          }
        }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Send both threadId and resourceId together in the request body (or supply the missing half via requestContext)
  2. If you don't need memory, omit both fields and call without thread persistence
  3. Migrate off the deprecated generate-legacy route to /agents/:agentId/generate with matching current parameter handling

Example fix

// before
await client.generate({ threadId: 'thread-1' }); // resourceId missing
// after
await client.generate({ threadId: 'thread-1', resourceId: 'user-42' });
Defensive patterns

Strategy: validation

Validate before calling

function validateMemoryParams(p: { threadId?: string; resourceId?: string }): void {
  const hasThread = Boolean(p.threadId);
  const hasResource = Boolean(p.resourceId);
  if (hasThread !== hasResource) {
    throw new Error('threadId and resourceId must be provided together');
  }
}

Type guard

function hasCompleteMemoryPair(p: { threadId?: string; resourceId?: string }): p is { threadId: string; resourceId: string } {
  return typeof p.threadId === 'string' && p.threadId.length > 0 &&
         typeof p.resourceId === 'string' && p.resourceId.length > 0;
}

Try / catch

try {
  await client.generateLegacy({ messages, threadId });
} catch (e) {
  if (isHttpException(e, 400) && String(e.message).includes('threadId or resourceId')) {
    // add the missing half or drop both
  }
}

Prevention

When it happens

Trigger: Calling generate-legacy with threadId but no resourceId (or vice versa) in the body — remembering that requestContext can supply the effective value, so a body resourceId paired with a threadId-only requestContext (or the reverse) also triggers it.

Common situations: Older clients that only sent threadId; code migrated from an API where resourceId was optional; server middleware injecting resourceId via requestContext while the client still sends only threadId, leaving the other half unset.

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/7127cf8db3c18e24. Report an issue: GitHub.