mastra-ai/mastra · error
Could not fetch metadata for thread ${threadId} while saving
Error message
Could not fetch metadata for thread ${threadId} while saving semantic recall embeddings: ${message} What it means
While batch-saving semantic recall embeddings, Memory fetches each thread to read its metadata (needed for per-thread/per-resource embedding scoping). If that fetch throws for any thread, the original error is wrapped and rethrown with the threadId and underlying message so you know which thread and why the storage read failed.
Source
Thrown at packages/memory/src/index.ts:1398
if (message.threadId) {
if (!messagesByThread.has(message.threadId)) {
messagesByThread.set(message.threadId, []);
}
messagesByThread.get(message.threadId)!.push(message);
}
});
const threadMetadataMap = new Map<string, Record<string, unknown>>();
await Promise.all(
Array.from(messagesByThread.keys()).map(async threadId => {
try {
const thread = await memoryStore.getThreadById({ threadId });
if (thread?.metadata) {
threadMetadataMap.set(threadId, thread.metadata);
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(
`Could not fetch metadata for thread ${threadId} while saving semantic recall embeddings: ${message}`,
);
}
}),
);
// Collect all embeddings first (embedding is CPU-bound, doesn't use pool connections)
const embeddingData: Array<{
embeddings: number[][];
metadata: Array<
Record<string, unknown> & {
message_id: string;
thread_id: string | undefined;
resource_id: string | undefined;
}
>;
}> = [];
let dimension: number | undefined;View on GitHub (pinned to 75dd419e61)
Solutions
- Read the inner message after the colon to find the real storage error and fix it (connectivity, credentials, missing table).
- Verify the memory storage adapter is healthy: run a simple getThreadById on the failing threadId against the same store.
- Ensure threads are created before messages referencing them are remembered, and that concurrent jobs do not delete threads mid-save.
- Retry the operation if the underlying cause was a transient connection error.
Example fix
// before — silently deleting threads while saving
await threadsCollection.deleteOne({ id: threadId });
await memory.remember({ threadId, resourceId, messages });
// after — verify thread exists first
const thread = await memory.getThreadById({ threadId });
if (thread) {
await memory.remember({ threadId, resourceId, messages });
} Defensive patterns
Strategy: try-catch
Validate before calling
const thread = await memory.getThreadById({ threadId });
if (!thread) throw new Error(`Refusing to remember for missing thread ${threadId}`); Type guard
function isMetadataFetchError(e: unknown, threadId: string): e is Error {
return e instanceof Error && e.message.includes(`Could not fetch metadata for thread ${threadId}`);
} Try / catch
try {
await memory.remember({ threadId, resourceId, messages });
} catch (e) {
if (e instanceof Error && e.message.includes('Could not fetch metadata for thread')) {
logger.error({ err: e }, 'Storage failure while saving embeddings'); // inner message names the real cause
if (isTransient(e.message)) await retry(() => memory.remember({ threadId, resourceId, messages }), { retries: 3 });
} else throw e;
} Prevention
- Monitor storage adapter health (connectivity, pool usage) since the inner error is the real cause.
- Avoid deleting threads concurrently with embedding saves.
- Run schema migrations for the memory store before deploying embedding-dependent code.
When it happens
Trigger: Calling remember() with messages whose threadId no longer resolves in the memory store while the storage adapter raises an error (connection failure, deleted table, permissions) — distinct from a plain not-found, which is tolerated.
Common situations: Storage DB temporarily unreachable (network blip, pool exhaustion); concurrent deletion of threads during embedding save; misconfigured storage adapter credentials; schema migrations dropping the threads table.
Related errors
- @mastra/opencode: failed to initialize memory storage from $
- sendStateSignal could not load thread ${threadId}
- Storage is not configured on this AgentController
- Storage does not have a memory domain configured
- Memory is not configured on this AgentController
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4a57456113c8042e.
Report an issue: GitHub.