mastra-ai/mastra · error
Thread with id ${id} not found
Error message
Thread with id ${id} not found What it means
InMemoryStorage.updateThread throws when no thread exists in the in-memory store with the given id. The lookup this.db.threads.get(id) returns undefined and the library fails fast rather than silently creating or no-oping an update.
Source
Thrown at packages/core/src/storage/domains/memory/inmemory.ts:87
async saveThread({ thread }: { thread: StorageThreadType }): Promise<StorageThreadType> {
const key = thread.id;
this.db.threads.set(key, thread);
return thread;
}
async updateThread({
id,
title,
metadata,
}: {
id: string;
title?: string;
metadata?: Record<string, unknown>;
}): Promise<StorageThreadType> {
const thread = this.db.threads.get(id);
if (!thread) {
throw new Error(`Thread with id ${id} not found`);
}
if (thread) {
if (title !== undefined) thread.title = title;
thread.metadata = { ...thread.metadata, ...metadata };
thread.updatedAt = new Date();
}
return thread;
}
async deleteThread({ threadId }: { threadId: string }): Promise<void> {
this.db.threads.delete(threadId);
this.db.messages.forEach((msg, key) => {
if (msg.thread_id === threadId) {
this.db.messages.delete(key);
}
});View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the thread exists (getThreadById / listThreads) before updating, or create it if missing.
- Persist threads with a real storage adapter (LibSQL/Postgres/etc.) so ids survive restarts.
- Ensure the same storage instance is used for create and update within the process.
- Log and handle the error as 'thread not found' (404-style) rather than a retryable failure.
Example fix
// before
await storage.updateThread({ id: threadId, title: 'New' }); // throws if missing
// after
const existing = await storage.getThreadById({ threadId });
if (!existing) {
await storage.saveThread({ thread: { id: threadId, title: 'New', createdAt: new Date(), updatedAt: new Date(), metadata: {} } });
} else {
await storage.updateThread({ id: threadId, title: 'New' });
} Defensive patterns
Strategy: try-catch
Validate before calling
async function updateThreadIfExists(storage, id, patch) {
const existing = await storage.getThreadById({ threadId: id });
if (!existing) return null;
return storage.updateThread({ id, ...patch });
} Type guard
function isThread(t: unknown): t is { id: string; title?: string; metadata?: Record<string, unknown> } {
return !!t && typeof (t as any).id === 'string';
} Try / catch
try {
await storage.updateThread({ id, title });
} catch (e) {
if (e instanceof Error && e.message === `Thread with id ${id} not found`) {
// create the thread or return 404 to the caller
return null;
}
throw e;
} Prevention
- Check existence with getThreadById before updating
- Use persistent storage adapters in production, not in-memory
- Do not reuse thread ids across storage instances or process restarts
When it happens
Trigger: Calling updateThread({ id }) with an id that was never created in the current process, or after the in-memory store was restarted/cleared; updating a thread from a different storage instance than the one that created it.
Common situations: Server restarts wiping the in-memory store while clients hold stale thread ids; switching between dev (in-memory) and prod (persistent) storage; typos or case mismatches in thread ids; tests reusing ids across fresh storage instances.
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
- Agent with id ${id} not found
- Dataset not found: ${args.id}
- Dataset not found: ${args.datasetId}
- Item not found: ${args.id}
- MCP client with id ${id} not found
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/32ea06c1fb30d0c4.
Report an issue: GitHub.