mastra-ai/mastra · error · HTTPException
thread "${requestedThreadId}" not found
Error message
thread "${requestedThreadId}" not found What it means
When a session endpoint is called with an explicit `requestedThreadId`, the handler loads the thread via the memory store scoped to the given resourceId and throws HTTP 404 if no matching thread exists. This ensures clients cannot attach a session to a nonexistent (or other-resource) thread.
Source
Thrown at packages/server/src/server/handlers/agent-controller.ts:820
pathParamSchema: sessionPathParams,
queryParamSchema: sessionStateQuerySchema,
responseSchema: sessionStateResponseSchema,
summary: 'Get session state',
description: 'Returns the current mode, model, thread, and durable tasks for initial UI hydration.',
tags: ['AgentController'],
requiresAuth: true,
requiresPermission: 'agent-controller:read',
handler: async ({ mastra, controllerId, resourceId, sessionScope, threadId: requestedThreadId, requestContext }) => {
try {
const controller = getAgentControllerOrThrow(mastra, controllerId);
const session = await getSession(controller, resourceId, { scope: sessionScope }, requestContext);
const ds = session.displayState.get();
const threadId = requestedThreadId ?? session.thread.getId() ?? undefined;
const storage = mastra.getStorage();
if (requestedThreadId) {
const memory = await storage?.getStore('memory');
const thread = await memory?.getThreadById({ threadId: requestedThreadId, resourceId });
if (!thread) throw new HTTPException(404, { message: `thread "${requestedThreadId}" not found` });
}
const threadState = threadId ? await storage?.getStore('threadState') : undefined;
const storedTasks = threadId ? await threadState?.getState<unknown>({ threadId, type: 'task' }) : undefined;
const parsedTasks = taskSnapshotSchema.array().safeParse(storedTasks);
const tasks: SessionTaskSnapshot[] = parsedTasks.success ? parsedTasks.data : [];
const om = ds.omProgress;
const reflectionSavings =
om.buffered.reflection.inputObservationTokens - om.buffered.reflection.observationTokens;
const st = session.state.get() as Record<string, unknown>;
const oneOf = <T extends string>(value: unknown, allowed: readonly T[], fallback: T): T =>
allowed.includes(value as T) ? (value as T) : fallback;
const oneOfOptional = <T extends string>(value: unknown, allowed: readonly T[]): T | undefined =>
allowed.includes(value as T) ? (value as T) : undefined;
return {
controllerId,
resourceId,
threadId,
modeId: session.mode.get(),View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the threadId exists and belongs to the same resourceId — drop the explicit threadId to let the session create/reuse its own thread.
- Create the thread first (via the session/thread creation endpoint) before referencing it.
- Check storage configuration: ensure the memory store backing the server is the one that contains the thread.
- Clear stale client-side thread id caches after restarts or storage migrations.
Example fix
// before
const s = await api.createSession({ resourceId, threadId: savedThreadId }); // 404 after storage reset
// after
const s = await api.createSession({ resourceId }); // let server create/reuse a thread Defensive patterns
Strategy: try-catch
Validate before calling
const thread = await memoryClient.getThreadById({ threadId: requestedThreadId, resourceId });
if (!thread) throw new Error(`Thread ${requestedThreadId} does not exist for ${resourceId}; omit threadId to create one`); Type guard
function threadExists(t: { id: string } | null | undefined, id: string): t is { id: string } {
return !!t && t.id === id;
} Try / catch
try {
session = await api.createSession({ resourceId, threadId: requestedThreadId });
} catch (e) {
if (isHttpError(e) && e.status === 404 && e.message.includes('not found')) {
session = await api.createSession({ resourceId }); // create a fresh thread
} else throw e;
} Prevention
- Don't persist thread ids across storage resets or environments.
- Always pass the resourceId that owns the thread.
- Fall back to server-created threads instead of assuming ids.
When it happens
Trigger: Passing a threadId in the request body/params that was never created, was deleted, belongs to a different resourceId (resource scoping is applied in getThreadById), or whose storage backend changed (e.g. switched storage domains and old thread ids no longer resolve).
Common situations: Client caches thread ids across environments (dev vs prod storage); in-memory storage reset on server restart so old ids vanish; resourceId mismatch because the identity/resource changed; typos in persisted thread id.
Related errors
- No thread found with id ${threadId}
- Thread ${threadId} not found
- Thread not found
- Source thread not found
- Model "${modelId}" is not available. Available models: ${ids
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/993d7439e12c2a31.
Report an issue: GitHub.