{"record":{"id":"72eb0717aaff292a","repo":"mastra-ai/mastra","slug":"thread-id-is-required-for-recall","errorCode":null,"errorMessage":"Thread ID is required for recall","messagePattern":"Thread ID is required for recall","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/memory/src/tools/om-tools.ts","lineNumber":795,"sourceCode":"  threadScope?: string;\n  maxTokens?: number;\n}): Promise<{\n  text: string;\n  messageId: string;\n  partIndex: number;\n  role: string;\n  type: string;\n  truncated: boolean;\n  charOffset: number;\n  nextCharOffset?: number;\n  note?: string;\n}> {\n  if (!memory || typeof memory.getMemoryStore !== 'function') {\n    throw new Error('Memory instance is required for recall');\n  }\n\n  if (!threadId) {\n    throw new Error('Thread ID is required for recall');\n  }\n\n  const resolved = await resolveCursorMessage(memory, cursor, {\n    resourceId,\n    threadScope,\n    enforceThreadScope: false,\n  });\n\n  if ('hint' in resolved) {\n    throw new Error(resolved.hint);\n  }\n\n  const allParts = formatMessageParts(resolved, 'high');\n\n  if (allParts.length === 0) {\n    throw new Error(\n      `Message ${cursor} has no visible content (it may be an internal system message). Try a neighboring message ID instead.`,\n    );","sourceCodeStart":777,"sourceCodeEnd":813,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/tools/om-tools.ts#L777-L813","documentation":"The recall reader requires a `threadId` to anchor the recall operation; it throws if the value is falsy. The thread identifies which conversation's messages to read, and cursor resolution plus message ordering all depend on it.","triggerScenarios":"Calling recallMessages/recallDetail without threadId; passing an empty-string threadId from an uninitialized variable; a chat flow that starts before a thread is created and the tool runs anyway; agent runtime not propagating memory.threadId into the tool args.","commonSituations":"First message of a conversation where thread creation is lazy; custom integration that constructs tool args manually; older code path that treated threadId as optional.","solutions":["Create or obtain the thread ID first (memory.createThread / runtime.getMemoryThread) and pass it explicitly.","Guard the call: if (!threadId) skip recall or initialize the thread.","When wiring the agent tool, bind threadId from the runtime context server-side rather than trusting model-provided args."],"exampleFix":"// before\nawait recallMessages({ memory, threadId: thread?.id ?? '', cursor });\n// after\nif (!thread?.id) {\n  thread = await memory.createThread({ resourceId });\n}\nawait recallMessages({ memory, threadId: thread.id, cursor });","handlingStrategy":"validation","validationCode":"if (!threadId) {\n  throw new Error('threadId is required; create or resolve the thread before recalling.');\n}","typeGuard":"function hasThreadId(args: { threadId?: string | null }): args is { threadId: string } {\n  return typeof args.threadId === 'string' && args.threadId.length > 0;\n}","tryCatchPattern":"try {\n  return await recallMessages({ memory, threadId, cursor });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Thread ID is required')) {\n    const thread = await memory.createThread({ resourceId: resourceId ?? 'default' });\n    return recallMessages({ memory, threadId: thread.id, cursor });\n  }\n  throw e;\n}","preventionTips":["Create the thread before the first agent turn and pass its ID into every tool call.","Bind threadId in the tool execute closure from runtime memory context instead of model args.","Guard chat bootstrapping so recall tools don't run pre-thread."],"tags":["validation","memory","thread-id"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}