mastra-ai/mastra · error · Error
Found unhandled message ${JSON.stringify(message)}
Error message
Found unhandled message ${JSON.stringify(message)} What it means
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.
Source
Thrown at packages/core/src/agent/message-list/conversion/input-converter.ts:151
}
if (TypeDetector.isAIV5UIMessage(message)) {
const dbMsg = AIV5Adapter.fromUIMessage(message);
// Only use the original createdAt from input message, not the generated one from the static method
// This fixes issue #10683 where messages without createdAt would get shuffled
const rawCreatedAt = 'createdAt' in message ? message.createdAt : undefined;
return stampMessageParts(
{
...dbMsg,
id,
createdAt: context.generateCreatedAt(messageSource, rawCreatedAt),
threadId: context.memoryInfo?.threadId,
resourceId: context.memoryInfo?.resourceId,
},
messageSource,
);
}
throw new Error(`Found unhandled message ${JSON.stringify(message)}`);
}
/**
* Convert MastraMessageV1 format to MastraDBMessage.
*/
export function mastraMessageV1ToMastraDBMessage(
message: MastraMessageV1,
messageSource: MessageSource,
context: InputConversionContext,
): MastraDBMessage {
const coreV2 = AIV4Adapter.fromCoreMessage(
{
content: message.content,
role: message.role,
} as CoreMessageV4,
context,
messageSource,
);View on GitHub (pinned to 75dd419e61)
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.
Example fix
// before
memory.add({ role: 'visitor', content: 'hello' });
// after
memory.add({ role: 'user', content: 'hello' }); // recognized CoreMessage shape Defensive patterns
Strategy: validation
Validate before calling
function isSupportedMessageInput(m: unknown): boolean {
if (typeof m !== 'object' || m === null) return false;
const msg = m as Record<string, unknown>;
return ['system', 'user', 'assistant', 'tool'].includes(String(msg.role)) &&
(typeof msg.content === 'string' || Array.isArray(msg.content) || msg.content == null);
}
// assert every message before memory/MessageList.add
messages.forEach((m, i) => { if (!isSupportedMessageInput(m)) throw new Error(`Unsupported message at index ${i}`); }); Type guard
function isCoreMessage(m: unknown): m is { role: 'system'|'user'|'assistant'|'tool'; content: string | unknown[] } {
return typeof m === 'object' && m !== null &&
['system', 'user', 'assistant', 'tool'].includes((m as any).role) &&
(typeof (m as any).content === 'string' || Array.isArray((m as any).content));
} Try / catch
try {
await memory.rememberMessages({ messages: inputs });
} catch (e) {
if (e instanceof Error && e.message.startsWith('Found unhandled message')) {
console.error('Unrecognized message shape:', e.message);
// fall back to converting inputs to V4 CoreMessages first
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Received input message with wrong threadId. Input ${message.
- Received input message with wrong resourceId. Input ${messag
- Could not generate title from input ${JSON.stringify(message
- AGENT_LIST_SUSPENDED_RUNS_INVALID_PER_PAGE
- AGENT_LIST_SUSPENDED_RUNS_INVALID_PAGE
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/defe976d0f9a4789.
Report an issue: GitHub.