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
- Fetch the thread first (GET /api/memory/threads/:threadId) and skip or surface the clone error if it is missing.
- Confirm the threadId belongs to the same storage backend the server is configured with.
- If the source list is cached, refresh it before cloning so deleted threads are not offered as clone sources.
- 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
- Verify the source thread exists immediately before cloning (avoid TOCTOU on cached lists).
- Never copy threadIds between environments with separate databases.
- Prune deleted threads from UI lists that offer clone actions.
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
- thread "${requestedThreadId}" not found
- Thread not found
- Received input message with wrong threadId. Input ${message.
- Thread with id ${threadId} resourceId does not match the cur
- [Processor:${processor.id}] computeStateSignal could not loa
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b20ad2341b302f33.
Report an issue: GitHub.