mastra-ai/mastra · error · Error
Memory instance cannot verify thread access for recall
Error message
Memory instance cannot verify thread access for recall
What it means
Thread-access verification in resource-scoped recall requires the Memory instance to implement getThreadById. When the provided memory object lacks this method, Mastra throws rather than skipping the ownership check, because silently skipping would allow cross-resource reads.
Source
Thrown at packages/memory/src/tools/om-tools.ts:1468
throw new Error(
isResourceScope
? 'No active thread context and no cursor or threadId was provided for mode="messages". Pass a threadId (use mode="threads" to discover thread IDs) or a message ID as cursor.'
: 'No active thread context for mode="messages". This tool is limited to the current thread and no current thread could be resolved.',
);
}
let targetThreadId: string | undefined;
let threadScope: string | undefined;
if (!isResourceScope) {
targetThreadId = currentThreadId;
threadScope = currentThreadId || undefined;
} else if (hasResolvedThreadId) {
if (!resourceId) {
throw new Error('Resource ID is required for recall');
}
if (!memory.getThreadById) {
throw new Error('Memory instance cannot verify thread access for recall');
}
const thread = await memory.getThreadById({ threadId: resolvedThreadId! });
if (!thread || thread.resourceId !== resourceId) {
throw new Error('Thread does not belong to the active resource');
}
targetThreadId = thread.id;
threadScope = thread.id;
} else {
targetThreadId = currentThreadId;
threadScope = currentThreadId || undefined;
}
if (hasCursor && !hasResolvedThreadId && !currentThreadId) {
if (!isResourceScope) {
throw new Error('Current thread is required when browsing by cursor');
}View on GitHub (pinned to 75dd419e61)
Solutions
- Use a full Mastra Memory instance (or upgrade @mastra/memory to a version that implements getThreadById).
- If using a custom storage/memory adapter, implement getThreadById({ threadId }).
- Update test mocks to include getThreadById.
Example fix
// before
const memory = { query: async () => ({}) } as any;
// after
import { Memory } from '@mastra/memory';
const memory = new Memory({ storage, options: { ... } }); Defensive patterns
Strategy: type-guard
Type guard
function isFullMemory(m: unknown): m is Memory & { getThreadById: NonNullable<Memory['getThreadById']> } {
return typeof (m as any)?.getThreadById === 'function';
} Try / catch
if (!isFullMemory(memoryOrContext)) {
throw new Error('Provided memory does not implement getThreadById; use a full Memory instance');
} Prevention
- Use the official Memory class from @mastra/memory, not hand-rolled stubs.
- Keep @mastra/core and @mastra/memory versions in sync.
- Make test mocks implement the full Memory surface (or use the real class with in-memory storage).
When it happens
Trigger: Passing a custom or partial Memory-like object (e.g. a stub, mock, or older memory class) as context.memory that does not define getThreadById, while mode="messages" resolves an explicit threadId in resource scope.
Common situations: Dependency/version mismatch where the injected memory implementation predates getThreadById; test doubles missing the method; wrapping Memory in a proxy that drops methods.
Related errors
- sendStateSignal requires Mastra memory
- Storage is not configured on this AgentController
- Storage does not have a memory domain configured
- Memory is not configured on this AgentController
- Dynamic memory factory returned empty value
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/1189b047266a3c29.
Report an issue: GitHub.