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

  1. Read the inner message after the colon to find the real storage error and fix it (connectivity, credentials, missing table).
  2. Verify the memory storage adapter is healthy: run a simple getThreadById on the failing threadId against the same store.
  3. Ensure threads are created before messages referencing them are remembered, and that concurrent jobs do not delete threads mid-save.
  4. 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

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


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