mastra-ai/mastra · error · MastraError

INVALID_MESSAGE_CONTENT

INVALID_MESSAGE_CONTENT

Error message

Message with role "${message.role}" must have either a 'content' property (string or array) or a 'parts' property (array) that is not empty, null, or undefined. Received message: ${JSON.stringify(message, null, 2)}

What it means

MessageList.add validates that every incoming message has usable content: either a 'content' string/array or a 'parts' array. A MastraError with id INVALID_MESSAGE_CONTENT (AGENT domain, USER category) is thrown when both are missing, null, or undefined, because an empty message cannot be stored or converted to a prompt.

Source

Thrown at packages/core/src/agent/message-list/message-list.ts:1649

    const existingMessage = this.getMessageById(message.id);
    if (!existingMessage) return { exists: false };

    return {
      exists: true,
      shouldReplace: !messagesAreEqual(existingMessage, message),
      id: existingMessage.id,
    };
  }

  private addOne(message: MessageInput, messageSource: MessageSource, options: MessageListAddOptions = {}) {
    if (
      (!(`content` in message) ||
        (!message.content &&
          // allow empty strings
          typeof message.content !== 'string')) &&
      (!(`parts` in message) || !message.parts)
    ) {
      throw new MastraError({
        id: 'INVALID_MESSAGE_CONTENT',
        domain: ErrorDomain.AGENT,
        category: ErrorCategory.USER,
        text: `Message with role "${message.role}" must have either a 'content' property (string or array) or a 'parts' property (array) that is not empty, null, or undefined. Received message: ${JSON.stringify(message, null, 2)}`,
        details: {
          role: message.role as string,
          messageSource,
          hasContent: 'content' in message,
          hasParts: 'parts' in message,
        },
      });
    }

    if (message.role === `system`) {
      // In the past system messages were accidentally stored in the db. these should be ignored because memory is not supposed to store system messages.
      if (messageSource === `memory`) return null;

      // Check if the message is in a supported format for system messages

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure every message has non-null 'content' (string '' allowed) or a non-empty 'parts' array before calling add()
  2. Validate/sanitize client-supplied messages at your API boundary
  3. Fix transformation code that strips the content field
  4. Catch MastraError with id INVALID_MESSAGE_CONTENT and reject the input upstream with a clearer message

Example fix

// before
add({ role: 'user', content: undefined })
// after
add({ role: 'user', content: '' }) // or omit the message entirely if empty
Defensive patterns

Strategy: validation

Validate before calling

function hasContent(m: any): boolean { return Boolean(m && m.role && ((('content' in m) && (typeof m.content === 'string' || Array.isArray(m.content))) || Array.isArray(m.parts))); }

Type guard

function isAddableMessage(m: any): m is { role: 'user'|'assistant'|'system'|'tool'; content: string | any[] } { return !!m && ['user','assistant','system','tool'].includes(m.role) && (typeof m.content === 'string' || Array.isArray(m.content) || Array.isArray(m.parts)); }

Try / catch

try { messageList.add(msg); } catch (e) { if (e instanceof MastraError && e.id === 'INVALID_MESSAGE_CONTENT') { console.warn('Skipping empty message', msg); return; } throw e; }

Prevention

When it happens

Trigger: Adding messages like { role: 'user' } with no content, content: null, content: undefined, or an object with parts: null — via messageList.add(), Memory remember/add flows, or client-supplied message payloads.

Common situations: API clients posting empty messages; failed LLM responses persisted with undefined content; JS callers (no type checking) omitting content; mapping code that drops content during transformation.

Related errors


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