{"record":{"id":"9e8d32371676b47f","repo":"mastra-ai/mastra","slug":"received-input-message-with-wrong-threadid-input","errorCode":null,"errorMessage":"Received input message with wrong threadId. Input ${message.threadId}, expected ${context.memoryInfo.threadId}","messagePattern":"Received input message with wrong threadId\\. Input (.+?), expected (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/conversion/input-converter.ts","lineNumber":44,"sourceCode":"\n/**\n * Convert any supported message input format to MastraDBMessage.\n * Routes to the appropriate converter based on message type detection.\n */\nexport function inputToMastraDBMessage(\n  message: MessageInput,\n  messageSource: MessageSource,\n  context: InputConversionContext,\n): MastraDBMessage {\n  // Validate threadId matches (except for memory messages which can come from other threads)\n  if (\n    messageSource !== `memory` &&\n    `threadId` in message &&\n    message.threadId &&\n    context.memoryInfo &&\n    message.threadId !== context.memoryInfo.threadId\n  ) {\n    throw new Error(\n      `Received input message with wrong threadId. Input ${message.threadId}, expected ${context.memoryInfo.threadId}`,\n    );\n  }\n\n  // Validate resourceId matches (except for memory messages, which can carry a\n  // system resourceId — e.g. observational-memory continuation messages)\n  if (\n    messageSource !== `memory` &&\n    `resourceId` in message &&\n    message.resourceId &&\n    context.memoryInfo?.resourceId &&\n    message.resourceId !== context.memoryInfo.resourceId\n  ) {\n    throw new Error(\n      `Received input message with wrong resourceId. Input ${message.resourceId}, expected ${context.memoryInfo.resourceId}`,\n    );\n  }\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/conversion/input-converter.ts#L26-L62","documentation":"Error thrown by inputToMastraDBMessage when an input message carries a threadId that does not match the threadId of the memory context the agent is operating in. Memory-sourced messages (messageSource === 'memory') are exempt, but user/input messages must belong to the current thread to prevent cross-thread message injection.","triggerScenarios":"Calling agent.generate/stream with a messages array where a message has threadId set to a different thread than context.memoryInfo.threadId (e.g. passing remembered messages from another thread as direct input, or a stale client-side threadId after the agent switched threads).","commonSituations":"Client caching old thread IDs across conversations; copying messages between threads in custom code; resuming a stored conversation but passing the original thread's messages; multi-agent setups sharing message arrays across agents with different memory threads.","solutions":["Remove the threadId field from input messages and let the agent bind them to the current thread via memory options.","Set the message's threadId to match the thread the agent is running with (context.memoryInfo.threadId).","If intentionally reusing messages across threads, pass them with messageSource 'memory' or strip thread metadata before input.","Audit client code for stale threadId state after thread switches."],"exampleFix":"// before\nawait agent.generate(messages, { memory: { thread: otherThreadId, resource } }); // messages carry threadId: 'thread-A'\n\n// after\nconst cleaned = messages.map(({ threadId, resourceId, ...m }) => m);\nawait agent.generate(cleaned, { memory: { thread: currentThreadId, resource } });","handlingStrategy":"validation","validationCode":"function assertThreadMatches(messages: Array<{ threadId?: string }>, expectedThreadId: string): void {\n  for (const m of messages) {\n    if (m.threadId && m.threadId !== expectedThreadId) {\n      throw new Error(`Message threadId ${m.threadId} != expected ${expectedThreadId}`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await agent.generate(messages, { memory: { thread: threadId, resource } });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('wrong threadId')) {\n    const stripped = messages.map(({ threadId, ...m }) => m);\n    return agent.generate(stripped, { memory: { thread: threadId, resource } });\n  }\n  throw e;\n}","preventionTips":["Omit threadId/resourceId from input messages and let the agent's memory options set them.","Clear client-side cached message arrays when switching threads.","Only feed messages back via memory recall, not raw input, when they originate from another thread.","Write a test asserting cross-thread input is rejected or stripped."],"tags":["agent","memory","thread","input-validation"],"backgroundTag":"thread-id-mismatch","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}