mastra-ai/mastra · error · Error
Current thread is required when browsing by cursor
Error message
Current thread is required when browsing by cursor
What it means
When browsing messages by cursor (message ID) without a resolved threadId, non-resource-scoped memory has no way to locate the thread containing the cursor — it is limited to the current thread. Mastra throws because a current thread is mandatory in that path.
Source
Thrown at packages/memory/src/tools/om-tools.ts:1485
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');
}
const resolved = await resolveCursorMessage(memory, cursor!, { resourceId });
if ('hint' in resolved) {
return {
messages: resolved.hint,
count: 0,
cursor: cursor!,
page: page ?? 1,
limit: Math.min(limit ?? 20, 20),
detail: detail ?? 'low',
hasNextPage: false,
hasPrevPage: false,
truncated: false,
tokenOffset: 0,
};
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Pass threadId along with the cursor in the tool context.
- Enable resource scope so the cursor can be resolved across threads via resolveCursorMessage.
- Maintain the currentThreadId in the run context (invoke within an agent run that has a thread).
Example fix
// before
await recallTool.execute({ context: { mode: 'messages', cursor: 'msg-42' } });
// after
await recallTool.execute({ context: { mode: 'messages', cursor: 'msg-42', threadId: 'thread-abc' } }); Defensive patterns
Strategy: validation
Validate before calling
if (cursor && !threadId && !currentThreadId) {
throw new Error('threadId or an active thread is required when paginating with a cursor');
} Type guard
function cursorCallIsValid(a: { cursor?: string; threadId?: string; currentThreadId?: string }): boolean {
return !a.cursor || Boolean(a.threadId || a.currentThreadId);
} Try / catch
try {
return await recall({ mode: 'messages', cursor, threadId });
} catch (err) {
if (err instanceof Error && err.message === 'Current thread is required when browsing by cursor') {
return recall({ mode: 'messages', threadId: knownThreadId, cursor });
}
throw err;
} Prevention
- Carry threadId through every page of cursor pagination.
- Enable resource scope if you need cursor resolution across threads.
- Avoid raw cursors in scripts without thread context.
When it happens
Trigger: mode="messages" with a cursor but no threadId and no currentThreadId, while resource scope is disabled (so cursor-based thread resolution via resolveCursorMessage isn't used).
Common situations: Paginating history via cursor in a standalone script with no active agent thread; cursor continuation calls that drop threadId between pages.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- resourceId and threadId are required to queue a message
- resourceId and threadId are required to send a state signal
- resourceId and threadId are required to persist an active si
- Resource ID is required for resource-scoped working memory u
- Cannot update working memory: ${scope} ID is required
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e25560206f99ca2f.
Report an issue: GitHub.