BerriAI/litellm · error · Exception

kwarg `messages` must be an array of messages that follow…

Error message

kwarg `messages` must be an array of messages that follow the openai chat standard

What it means

Bytez's validate_environment raises this generic Exception when the messages kwarg is empty (falsy). It is a request-shape guard: Bytez needs at least one message to build the chat request. Note it fires before the api_key check in the same method, so an empty-messages call reports this rather than the missing-key error.

Solutions

  1. Ensure at least one message, typically a user turn, before calling: guard with `if not messages: append fallback`.
  2. Fix the upstream slicing/filtering that emptied the list.
  3. Add a unit test on your prompt builder asserting non-empty messages.

Example fix

# before
messages = [m for m in history if keep(m)]  # can become []
litellm.completion(model="bytez/...", messages=messages)

# after
messages = [m for m in history if keep(m)] or [{"role": "user", "content": "Hello"}]
litellm.completion(model="bytez/...", messages=messages)
Defensive patterns

Strategy: validation

Validate before calling

def has_messages(messages) -> bool:
    return isinstance(messages, list) and len(messages) > 0

assert has_messages(messages), "refusing to call bytez with empty messages"

Type guard

from typing import Any

def is_nonempty_message_list(messages: Any) -> bool:
    return (
        isinstance(messages, list)
        and len(messages) > 0
        and all(isinstance(m, dict) and m.get("role") and "content" in m for m in messages)
    )

Try / catch

try:
    litellm.completion(model="bytez/org/model", messages=messages)
except Exception as e:
    if "messages" in str(e) and not messages:
        messages = [{"role": "user", "content": "Hello"}]
        litellm.completion(model="bytez/org/model", messages=messages)
    else:
        raise

Prevention

When it happens

Trigger: litellm.completion(model="bytez/...", messages=[]) or messages=None; templates/chat-history slicing that accidentally yields an empty list (e.g., trimming context too aggressively); passing conversation history that failed to populate from a DB.

Common situations: Dynamic prompt builders trimming history to zero turns; early-exit branches that still call the LLM; None default leaking through instead of a user message.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/12f9aec9f80d3005. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/bytez/chat/transformation.py:135

        self,
        headers: dict,
        model: str,
        messages: list[AllMessageValues],
        optional_params: dict,
        litellm_params: dict,
        api_key: str | None = None,
        api_base: str | None = None,
    ) -> dict:
        headers.update(
            {
                "content-type": "application/json",
                "Authorization": f"Key {api_key}",
                "user-agent": f"litellm/{version}",
            }
        )

        if not messages:
            raise Exception("kwarg `messages` must be an array of messages that follow the openai chat standard")

        if not api_key:
            raise Exception("Missing api_key, make sure you pass in your api key")

        return headers

    def get_complete_url(
        self,
        api_base: str | None,
        api_key: str | None,
        model: str,
        optional_params: dict,
        litellm_params: dict,
        stream: bool | None = None,
    ) -> str:
        encoded_model: Final = encode_url_path_segments(model, field_name="model")
        return f"{API_BASE}/{encoded_model}"

View on GitHub (pinned to 77b7c6c40c)