eyaltoledano/claude-task-master · error · Error
Invalid message format. Each message must have role and cont
Error message
Invalid message format. Each message must have role and content
What it means
This error is thrown by BaseAIProvider.validateMessages when a message in the messages array is missing either a 'role' or a 'content' property. The base provider requires every message to be a well-formed {role, content} object before it is forwarded to the underlying AI SDK. It guards all four entry points: generateText, streamText, generateObject and streamObject.
Source
Thrown at src/ai-providers/base-provider.js:242
if (params.maxTokens !== undefined) {
const maxTokens = Number(params.maxTokens);
if (!Number.isFinite(maxTokens) || maxTokens <= 0) {
throw new Error('maxTokens must be a finite number greater than 0');
}
}
}
/**
* Validates message array structure
*/
validateMessages(messages) {
if (!messages || !Array.isArray(messages) || messages.length === 0) {
throw new Error('Invalid or empty messages array provided');
}
for (const msg of messages) {
if (!msg.role || !msg.content) {
throw new Error(
'Invalid message format. Each message must have role and content'
);
}
}
}
/**
* Common error handler
*/
handleError(operation, error) {
const errorMessage = error.message || 'Unknown error occurred';
log('error', `${this.name} ${operation} failed: ${errorMessage}`, {
error
});
throw new Error(
`${this.name} API error during ${operation}: ${errorMessage}`
);
}View on GitHub (pinned to c0c98d367c)
Solutions
- Ensure every message object has both a truthy 'role' ('system'|'user'|'assistant') and truthy 'content' string
- Filter out incomplete messages before calling: messages.filter(m => m.role && m.content)
- Fix code that constructs messages so empty content yields either omission of the message or placeholder content
Example fix
// before
const messages = [{ role: 'user', content: userText }, { role: 'assistant', content: '' }];
await provider.generateText({ messages });
// after
const messages = [{ role: 'user', content: userText }, { role: 'assistant', content: '' }]
.filter(m => m.role && m.content);
await provider.generateText({ messages }); Defensive patterns
Strategy: validation
Validate before calling
function validateMessagesBeforeCall(messages) {
if (!Array.isArray(messages) || messages.length === 0) throw new Error('messages must be a non-empty array');
messages.forEach((m, i) => {
if (!m || typeof m !== 'object' || !m.role || !m.content) throw new Error(`messages[${i}] must have role and content`);
});
} Type guard
function isValidMessage(m) {
return typeof m === 'object' && m !== null && typeof m.role === 'string' && m.role.length > 0 && typeof m.content === 'string' && m.content.length > 0;
} Try / catch
try {
await provider.generateText({ messages });
} catch (e) {
if (e.message === 'Invalid message format. Each message must have role and content') {
console.error('Malformed message array:', messages.filter(m => !m?.role || !m?.content));
} else throw e;
} Prevention
- Filter message arrays with .filter(m => m.role && m.content) before every call
- Centralize message construction in one helper that enforces {role, content}
- Unit-test prompt builders to guarantee well-formed messages
When it happens
Trigger: Calling generateText/streamText/generateObject/streamObject with a messages array where at least one element lacks 'role' or 'content' (or has them set to empty string/null/undefined). E.g. messages: [{ role: 'user' }] or messages: [{ content: 'hi' }].
Common situations: Building message arrays programmatically and pushing partial objects; older message formats from a different library that use e.g. {author, text}; conditionally-built prompts where an assistant message got an empty content string after filtering; forgetting to include content on system messages.
Related errors
- Manual task data must include at least a title and descripti
- Subtask ID cannot be empty.
- Invalid or empty messages array provided
- INPUT_VALIDATION_ERROR
- INPUT_VALIDATION_ERROR
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/2dfc98bda3504e96.
Report an issue: GitHub.