{"record":{"id":"defe976d0f9a4789","repo":"mastra-ai/mastra","slug":"found-unhandled-message-json-stringify-message","errorCode":null,"errorMessage":"Found unhandled message ${JSON.stringify(message)}","messagePattern":"Found unhandled message (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/conversion/input-converter.ts","lineNumber":151,"sourceCode":"  }\n  if (TypeDetector.isAIV5UIMessage(message)) {\n    const dbMsg = AIV5Adapter.fromUIMessage(message);\n    // Only use the original createdAt from input message, not the generated one from the static method\n    // This fixes issue #10683 where messages without createdAt would get shuffled\n    const rawCreatedAt = 'createdAt' in message ? message.createdAt : undefined;\n    return stampMessageParts(\n      {\n        ...dbMsg,\n        id,\n        createdAt: context.generateCreatedAt(messageSource, rawCreatedAt),\n        threadId: context.memoryInfo?.threadId,\n        resourceId: context.memoryInfo?.resourceId,\n      },\n      messageSource,\n    );\n  }\n\n  throw new Error(`Found unhandled message ${JSON.stringify(message)}`);\n}\n\n/**\n * Convert MastraMessageV1 format to MastraDBMessage.\n */\nexport function mastraMessageV1ToMastraDBMessage(\n  message: MastraMessageV1,\n  messageSource: MessageSource,\n  context: InputConversionContext,\n): MastraDBMessage {\n  const coreV2 = AIV4Adapter.fromCoreMessage(\n    {\n      content: message.content,\n      role: message.role,\n    } as CoreMessageV4,\n    context,\n    messageSource,\n  );","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/conversion/input-converter.ts#L133-L169","documentation":"inputToMastraDBMessage in packages/core/src/agent/message-list/conversion/input-converter.ts:151 normalizes any supported message format (Mastra V1, MastraDBMessage, AI SDK V4/V5/V6 Core and UI messages) into MastraDBMessage via a chain of TypeDetector checks. This final throw means the object matched NONE of the known detectors, so Mastra has no converter for it. It is a guard against silently ingesting an unrecognized message shape.","triggerScenarios":"Passing a message object to mastra.getMemory().rememberMessages()/MessageList.add (or agent memory input) that is none of: MastraMessageV1, MastraDBMessage, AI SDK V4 CoreMessage, V4 UIMessage, V5 CoreMessage/ModelMessage, V5 UIMessage, V6 CoreMessage/ModelMessage, V6 UIMessage — e.g. a plain {role:'user',content:'hi'} object, a serialized/JSON round-tripped message missing distinguishing fields, or a custom message type.","commonSituations":"Hand-rolling message objects instead of using AI SDK helpers; upgrading AI SDK major versions so detection fails; deserializing messages from a queue/DB losing prototype fields; passing Message or AssistantMessage response objects directly instead of their .messages.","solutions":["Construct messages with AI SDK helpers (e.g. { role, content } as CoreMessage with a recognized role of 'system'|'user'|'assistant'|'tool' and string or parts-array content) so TypeDetector matches them.","Log the offending object and compare against the TypeDetector.is* predicates in packages/core/src/agent/message-list/detection/TypeDetector.ts to find which expected field is missing.","If coming from a custom format, convert it to a supported format (V4 CoreMessage or UIMessage) before adding to memory/MessageList.","Check AI SDK version alignment with the installed @mastra/core; upgrade or downgrade so message types are among the supported V4/V5/V6 shapes."],"exampleFix":"// before\nmemory.add({ role: 'visitor', content: 'hello' });\n// after\nmemory.add({ role: 'user', content: 'hello' }); // recognized CoreMessage shape","handlingStrategy":"validation","validationCode":"function isSupportedMessageInput(m: unknown): boolean {\n  if (typeof m !== 'object' || m === null) return false;\n  const msg = m as Record<string, unknown>;\n  return ['system', 'user', 'assistant', 'tool'].includes(String(msg.role)) &&\n    (typeof msg.content === 'string' || Array.isArray(msg.content) || msg.content == null);\n}\n// assert every message before memory/MessageList.add\nmessages.forEach((m, i) => { if (!isSupportedMessageInput(m)) throw new Error(`Unsupported message at index ${i}`); });","typeGuard":"function isCoreMessage(m: unknown): m is { role: 'system'|'user'|'assistant'|'tool'; content: string | unknown[] } {\n  return typeof m === 'object' && m !== null &&\n    ['system', 'user', 'assistant', 'tool'].includes((m as any).role) &&\n    (typeof (m as any).content === 'string' || Array.isArray((m as any).content));\n}","tryCatchPattern":"try {\n  await memory.rememberMessages({ messages: inputs });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Found unhandled message')) {\n    console.error('Unrecognized message shape:', e.message);\n    // fall back to converting inputs to V4 CoreMessages first\n  } else throw e;\n}","preventionTips":["Always build messages via AI SDK helpers instead of ad-hoc objects","Run the TypeDetector-style role/content check at your system boundary","Watch for JSON round-trips stripping fields messages rely on for detection","Keep @mastra/core and ai-sdk versions aligned"],"tags":["message-conversion","input-validation","agent","memory"],"backgroundTag":"unrecognized-message-format","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}