mastra-ai/mastra · error
recall requires a Memory instance with storage access
Error message
recall requires a Memory instance with storage access
What it means
recallMessages() needs more than any object that resembles memory — it explicitly checks typeof memory.getMemoryStore === 'function' to prove the instance exposes storage-backed methods (getMemoryStore, recall, getThreadById). Passing a duck-typed stub, a plain config object, or a different class (e.g. a store rather than a Memory) fails this duck-type check and throws.
Source
Thrown at packages/memory/src/tools/om-tools.ts:927
cursor: string;
page?: number;
limit?: number;
detail?: RecallDetail;
partType?: 'text' | 'tool-call' | 'tool-result' | 'reasoning' | 'image' | 'file';
toolName?: string;
threadScope?: string;
maxTokens?: number;
}): Promise<RecallResult> {
if (!memory) {
throw new Error('Memory instance is required for recall');
}
if (!threadId) {
throw new Error('Thread ID is required for recall');
}
if (typeof memory.getMemoryStore !== 'function') {
throw new Error('recall requires a Memory instance with storage access');
}
const MAX_PAGE = 50;
const MAX_LIMIT = 20;
const rawPage = page === 0 ? 1 : page;
const normalizedPage = Math.max(Math.min(rawPage, MAX_PAGE), -MAX_PAGE);
const normalizedLimit = Math.min(limit, MAX_LIMIT);
const resolved = await resolveCursorMessage(memory, cursor, {
resourceId,
threadScope,
enforceThreadScope: false,
});
if ('hint' in resolved) {
return {
messages: resolved.hint,
count: 0,View on GitHub (pinned to 75dd419e61)
Solutions
- Pass a real Memory instance: new Memory({ storage, options }) from @mastra/memory, not a config object or storage instance.
- If memory crossed a serialization boundary, reconstruct it with new Memory(config) on the consuming side.
- Update mocks in tests to implement getMemoryStore (and recall/getThreadById) as functions.
- Check @mastra/core and @mastra/memory versions align so the expected method exists.
Example fix
// before
await recallMessages({ memory: { ...memoryConfig }, threadId, cursor });
// after
import { Memory } from '@mastra/memory';
const memory = new Memory({ storage });
await recallMessages({ memory, threadId, cursor }); Defensive patterns
Strategy: type-guard
Validate before calling
// before calling recallMessages
if (typeof (memory as any)?.getMemoryStore !== 'function') {
throw new Error('Pass a Memory instance (new Memory(...)), not a config object or storage');
} Type guard
function isStorageBackedMemory(m: unknown): m is RecallMemory {
return (
!!m &&
typeof m === 'object' &&
typeof (m as any).getMemoryStore === 'function' &&
typeof (m as any).recall === 'function'
);
} Try / catch
try {
return await recallMessages({ memory, threadId, cursor });
} catch (err) {
if (err instanceof Error && err.message.includes('storage access')) {
memory = new Memory(memoryConfig); // rebuild from config
return await recallMessages({ memory, threadId, cursor });
}
throw err;
} Prevention
- Never serialize Memory instances; reconstruct with new Memory(config) after crossing boundaries.
- Keep @mastra/core and @mastra/memory versions in sync.
- In tests, mock the full surface (getMemoryStore, recall, getThreadById), not just recall.
When it happens
Trigger: Calling recallMessages({ memory: <store or mock or wrong object>, threadId, cursor }) where memory exists and threadId is set, but the object lacks a getMemoryStore method — e.g. passing a MastraStorage instance, a serialized/parsed Memory copy (methods lost through JSON), or a hand-rolled mock.
Common situations: Persisting a Memory instance via JSON (class methods dropped on revival); passing the memory *config* object instead of a `new Memory(config)` instance; mocking Memory in tests with only `recall` stubbed; importing Memory from mismatched package versions where the method was renamed.
Understand the failure class
Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.
Related errors
- MastraClient.deleteThread() requires exactly one of agentId
- No response body
- @mastra/opencode: failed to initialize memory storage from $
- Could not generate title from input ${JSON.stringify(message
- AGENT_MEMORY_THREAD_RESOURCE_MISMATCH
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/847d4e9e70a9ace4.
Report an issue: GitHub.