mastra-ai/mastra · error · MastraError

INVALID_SYSTEM_MESSAGE_FORMAT

INVALID_SYSTEM_MESSAGE_FORMAT

Error message

Invalid system message format. System messages must include 'role' and 'content' properties. The content should be a string.

What it means

MastraError thrown by MessageList's systemToV4Core when converting a stored system message into AI SDK v4 CoreMessage format. A system message must have role === 'system' and a non-empty content.content string; otherwise the adapter cannot produce a valid CoreMessage. It is categorized USER because the malformed message came from caller input, not the library.

Source

Thrown at packages/core/src/agent/message-list/adapters/AIV4Adapter.ts:377

      role: m.role === 'signal' ? (isUserMessageSignal ? 'user' : 'system') : m.role,
      content: m.role === 'signal' && !isUserMessageSignal ? '' : m.content.content || contentString,
      createdAt: m.createdAt,
      parts: v4Parts,
      experimental_attachments: experimentalAttachments,
    };
    // Preserve metadata if present
    if (m.content.metadata) {
      uiMessage.metadata = m.content.metadata;
    }
    return uiMessage;
  }

  /**
   * Converts a MastraDBMessage system message directly to AIV4 CoreMessage format
   */
  static systemToV4Core(message: MastraDBMessage): CoreMessageV4 {
    if (message.role !== `system` || !message.content.content)
      throw new MastraError({
        id: 'INVALID_SYSTEM_MESSAGE_FORMAT',
        domain: ErrorDomain.AGENT,
        category: ErrorCategory.USER,
        text: `Invalid system message format. System messages must include 'role' and 'content' properties. The content should be a string.`,
        details: {
          receivedMessage: JSON.stringify(message, null, 2),
        },
      });

    const coreMessage: CoreMessageV4 = { role: 'system', content: message.content.content };

    // Preserve message-level providerMetadata as experimental_providerMetadata (V4 field name)
    if (message.content.providerMetadata) {
      coreMessage.experimental_providerMetadata = message.content.providerMetadata;
    }

    return coreMessage;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the message is { role: 'system', content: { content: '...' } } with a non-empty string in content.content before adding it to MessageList.
  2. If starting from a plain string, wrap it: { role: 'system', content: { content: mySystemPrompt }, createdAt: new Date() }.
  3. Check persisted/storage records for system messages whose content was flattened or truncated and repair them.
  4. Inspect details.receivedMessage in the error to see the exact offending message.

Example fix

// before
const msg = { role: 'system', content: 'You are helpful.' };
messageList.add(msg);

// after
const msg = { role: 'system', content: { content: 'You are helpful.' } };
messageList.add(msg);
Defensive patterns

Strategy: validation

Validate before calling

function assertValidSystemMessage(msg: { role: string; content: unknown }): void {
  if (msg.role !== 'system' || typeof (msg.content as any)?.content !== 'string' || !(msg.content as any).content) {
    throw new Error(`Invalid system message: ${JSON.stringify(msg).slice(0, 200)}`);
  }
}

Type guard

function isSystemDBMessage(m: any): m is { role: 'system'; content: { content: string } } {
  return !!m && m.role === 'system' && typeof m.content?.content === 'string' && m.content.content.length > 0;
}

Try / catch

try {
  messageList.add(candidate);
} catch (e) {
  if (e instanceof MastraError && e.id === 'INVALID_SYSTEM_MESSAGE_FORMAT') {
    logger.error('Bad system message, skipping:', e.details.receivedMessage);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a message to MessageList/agent memory where message.role !== 'system' (e.g. 'System', 'assistant') but positioned as a system message, or a system message whose content.content is undefined/null/empty (e.g. { role: 'system', content: 'instructions' } string form instead of the structured content object, or content stripped during serialization).

Common situations: Constructing MastraDBMessage by hand with a plain-string content field; loading persisted messages from custom storage where content was stored as a string; mixing AI SDK message shapes with Mastra DB messages; typos like role: 'System'.

Related errors


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