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

  1. 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.
  2. 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.
  3. If coming from a custom format, convert it to a supported format (V4 CoreMessage or UIMessage) before adding to memory/MessageList.
  4. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/defe976d0f9a4789. Report an issue: GitHub.