linshenkx/prompt-optimizer · error · RequestConfigError

Messages array cannot be empty

Error message

Messages array cannot be empty

What it means

Thrown by validateMessages in the abstract LLM adapter when the messages array passed to sendMessage / sendMessageStream / sendMessageStreamWithTools has zero elements. The adapter refuses to build a provider request with no conversation content because every chat API requires at least one message. It is a client-side RequestConfigError raised before any network call.

Source

Thrown at packages/core/src/services/llm/adapters/abstract-adapter.ts:184

  ): Promise<void> {
    this.validateImageUnderstandingRequest(request)
    await this.doSendImageUnderstandingStream(request, config, callbacks)
  }

  // ===== 公共验证方法 =====

  /**
   * 验证消息数组格式
   * @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 {

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Ensure at least one message is included, typically the user's prompt: messages = [{role:'user', content: prompt}]
  2. If messages are built from history, append/prepend the current user turn after mapping history
  3. Add a guard before calling send* to short-circuit when messages.length === 0

Example fix

// before
await adapter.sendMessage([], { model: 'gpt-4' })

// after
await adapter.sendMessage([{ role: 'user', content: 'Hello' }], { model: 'gpt-4' })
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(messages) || messages.length === 0) {
  throw new Error('Refusing to call LLM with no messages')
}
await adapter.sendMessage(messages, opts)

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling sendMessage([], ...), sendMessageStream([]), or sendMessageStreamWithTools([]) with an empty array; building messages dynamically (e.g. mapping an empty history and forgetting a user prompt) and passing the result.

Common situations: Chat-history-driven apps where the history array is empty on first turn and the code forgets to prepend the user's message; filtering out all messages (e.g. by role) before sending; passing an uninitialized [] variable.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/393102b8c8cafcfa. Report an issue: GitHub.