mastra-ai/mastra · error · HTTPException

Source thread not found

Error message

Source thread not found

What it means

In CLONE_THREAD_ROUTE, after memory is resolved, the source thread is loaded with memory.getThreadById({ threadId }). If no thread exists for the path threadId, the handler throws HTTPException 404 'Source thread not found'. Cloning requires the source thread to be present and owned/accessible.

Source

Thrown at packages/server/src/server/handlers/memory.ts:1627

  description: 'Creates a copy of a conversation thread with all its messages',
  tags: ['Memory'],
  requiresAuth: true,
  handler: async ({ mastra, agentId, threadId, newThreadId, resourceId, title, metadata, options, requestContext }) => {
    try {
      const effectiveThreadId = getEffectiveThreadId(requestContext, threadId);
      const effectiveResourceId = getEffectiveResourceId(requestContext, resourceId);
      const effectiveNewThreadId = newThreadId ?? mastra.generateId();
      validateBody({ threadId: effectiveThreadId });

      const memory = await getMemoryFromContext({ mastra, agentId, requestContext });
      if (!memory) {
        throw new HTTPException(400, { message: 'Memory is not initialized' });
      }

      // Validate source thread ownership
      const sourceThread = await memory.getThreadById({ threadId: effectiveThreadId! });
      if (!sourceThread) {
        throw new HTTPException(404, { message: 'Source thread not found' });
      }
      const cloneResourceId = effectiveResourceId ?? sourceThread.resourceId ?? undefined;
      await enforceThreadAccess({
        mastra,
        requestContext,
        threadId: effectiveThreadId!,
        thread: sourceThread,
        effectiveResourceId,
      });
      await enforceThreadAccess({
        mastra,
        requestContext,
        threadId: effectiveNewThreadId,
        effectiveResourceId: cloneResourceId,
        permission: MastraFGAPermissions.MEMORY_WRITE,
      });
      const result = await memory.cloneThread({
        sourceThreadId: effectiveThreadId!,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Fetch the thread first (GET /api/memory/threads/:threadId) and skip or surface the clone error if it is missing.
  2. Confirm the threadId belongs to the same storage backend the server is configured with.
  3. If the source list is cached, refresh it before cloning so deleted threads are not offered as clone sources.
  4. Check any requestContext thread/resource overrides that might rewrite the effective threadId.

Example fix

// before
await client.post(`/memory/threads/${threadId}/clone`);

// after
const thread = await memory.getThreadById({ threadId });
if (!thread) throw new Error(`Cannot clone: thread ${threadId} does not exist`);
await client.post(`/memory/threads/${threadId}/clone`);
Defensive patterns

Strategy: validation

Validate before calling

const source = await memory.getThreadById({ threadId });
if (!source) {
  throw new Error(`Source thread ${threadId} not found; aborting clone`);
}

Type guard

function isThread(t: unknown): t is { id: string; resourceId: string; title?: string } {
  return !!t && typeof t === 'object' && typeof (t as any).id === 'string';
}

Try / catch

try {
  await memory.cloneThread({ sourceThreadId: threadId, newThreadId });
} catch (e) {
  if (e instanceof HTTPException && e.status === 404) {
    notifyUser('This conversation no longer exists and cannot be cloned');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/memory/threads/:threadId/clone with a threadId that does not exist in storage (already deleted, wrong environment/database, or never created), or a requestContext-threadId override pointing at a nonexistent thread.

Common situations: Cloning from a stale conversation list after the source thread was deleted by another user/tab; copying a threadId across dev/staging databases; racing with a delete that removes the thread before the clone executes.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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