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
- Ensure the message is { role: 'system', content: { content: '...' } } with a non-empty string in content.content before adding it to MessageList.
- If starting from a plain string, wrap it: { role: 'system', content: { content: mySystemPrompt }, createdAt: new Date() }.
- Check persisted/storage records for system messages whose content was flattened or truncated and repair them.
- 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
- Always build system messages via a helper that produces { role: 'system', content: { content: string } }.
- Never store/serialize system prompts as plain-string content in MastraDBMessage records.
- Validate messages loaded from custom storage before adding to MessageList.
- Check details.receivedMessage in the error payload to pinpoint the malformed record.
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
- INVALID_SYSTEM_MESSAGE_FORMAT
- AGENT_REQUEST_CONTEXT_VALIDATION_FAILED
- Either message or messages must be provided
- 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/4a72cc3d9061a9aa.
Report an issue: GitHub.