linshenkx/prompt-optimizer · error · RequestConfigError
Each message must have role and content
Error message
Each message must have role and content
What it means
Thrown by validateMessages when any element of the messages array lacks a truthy role or content field. The adapter validates each message shape before constructing the provider request; a message without role/content cannot be serialized into a chat completion. This is a client-side RequestConfigError thrown before any API call.
Source
Thrown at packages/core/src/services/llm/adapters/abstract-adapter.ts:189
// ===== 公共验证方法 =====
/**
* 验证消息数组格式
* @param messages 消息数组
* @throws {RequestConfigError} 当消息数组无效时
*/
protected validateMessages(messages: Message[]): void {
if (!Array.isArray(messages)) {
throw new RequestConfigError('Messages must be an array')
}
if (messages.length === 0) {
throw new RequestConfigError('Messages array cannot be empty')
}
for (const msg of messages) {
if (!msg.role || !msg.content) {
throw new RequestConfigError('Each message must have role and content')
}
if (!['system', 'user', 'assistant', 'tool'].includes(msg.role)) {
throw new RequestConfigError(`Invalid message role: ${msg.role}`)
}
if (typeof msg.content !== 'string') {
throw new RequestConfigError('Message content must be a string')
}
}
}
protected validateImageUnderstandingRequest(request: ImageUnderstandingRequest): void {
if (!request || typeof request !== 'object') {
throw new RequestConfigError('Image understanding request cannot be empty')
}
if (typeof request.userPrompt !== 'string' || !request.userPrompt.trim()) {View on GitHub (pinned to 3e677b1d9f)
Solutions
- Ensure every message has both a non-empty role and non-empty content
- If content can legitimately be empty (tool-call messages), use a placeholder like ' ' or check the API's expectations
- Validate messages with a type guard before calling send*
Example fix
// before
messages = [{ role: 'assistant' }]
// after
messages = [{ role: 'assistant', content: '(tool call)' }] Defensive patterns
Strategy: type-guard
Validate before calling
const ok = messages.every(m => m && typeof m.role === 'string' && m.role && typeof m.content === 'string' && m.content.length > 0)
if (!ok) throw new Error('Invalid message shape') Type guard
function isMessage(m: unknown): m is Message {
return !!m && typeof m === 'object'
&& typeof (m as Message).role === 'string' && (m as Message).role.length > 0
&& typeof (m as Message).content === 'string' && (m as Message).content.length > 0
} Try / catch
try { await adapter.sendMessage(msgs, opts) } catch (e) { if (e instanceof RequestConfigError && /role and content/.test(e.message)) { /* fix message shapes */ } else throw e } Prevention
- Type message arrays as Message[] instead of any[]
- Run messages.every(isMessage) before sending
- Remember empty-string content is rejected too
When it happens
Trigger: Passing objects like {role:'user'} (no content), {content:'hi'} (no role), or {role:'user', content:''} (empty string is falsy) in the messages array of sendMessage/sendMessageStream/sendMessageStreamWithTools.
Common situations: Constructing messages from untyped API payloads or JSON where fields are optional; tool-result messages where content was set to undefined; empty-string content (e.g. assistant messages representing tool calls) being rejected by the truthiness check.
Related errors
- Messages array cannot be empty
- Invalid message role: ${msg.role}
- Message content must be a string
- ${label} #${index + 1} must provide either assetId or b64.
- ${label} must not be empty.
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/5234e9699c4149ff.
Report an issue: GitHub.