oobabooga/textgen · error · InvalidRequestError

messages is required

Error message

messages is required

What it means

chat_completions_common requires a 'messages' key in the chat completions request body; it is the minimal contract for building the prompt. Missing it raises InvalidRequestError (400) with param='messages', matching the OpenAI API error shape.

Source

Thrown at modules/api/completions.py:485

    if not user_input_last:
        user_input = ""

    return user_input, system_message, {
        'internal': chat_dialogue,
        'visible': copy.deepcopy(chat_dialogue),
        'messages': history  # Store original messages for multimodal models
    }


def chat_completions_common(body: dict, is_legacy: bool = False, stream=False, prompt_only=False, stop_event=None) -> dict:
    if body.get('functions', []):
        raise InvalidRequestError(message="functions is not supported.", param='functions')

    if body.get('function_call', ''):
        raise InvalidRequestError(message="function_call is not supported.", param='function_call')

    if 'messages' not in body:
        raise InvalidRequestError(message="messages is required", param='messages')

    tools = None
    if 'tools' in body and body['tools'] is not None and isinstance(body['tools'], list) and body['tools']:
        tools = validateTools(body['tools'])  # raises InvalidRequestError if validation fails

    tool_choice = body.get('tool_choice', None)
    if tool_choice == "none":
        tools = None  # Disable tool detection entirely

    messages = body['messages']
    for m in messages:
        if 'role' not in m:
            raise InvalidRequestError(message="messages: missing role", param='messages')
        elif m['role'] == 'function':
            raise InvalidRequestError(message="role: function is not supported.", param='messages')

        # Handle multimodal content validation
        content = m.get('content')

View on GitHub (pinned to ed888c71f2)

Solutions

  1. Include a messages array: {"model": "...", "messages": [{"role": "user", "content": "hello"}]}.
  2. If you intended plain text completion, use /v1/completions with 'prompt' instead of the chat endpoint.
  3. Check the client is not stripping None/empty fields before sending.

Example fix

# before
curl $URL/v1/chat/completions -d '{"model": "model-x"}'

# after
curl $URL/v1/chat/completions -d '{"model": "model-x", "messages": [{"role": "user", "content": "hello"}]}'
Defensive patterns

Strategy: validation

Validate before calling

def valid_chat_body(body: dict) -> bool:
    msgs = body.get('messages')
    return isinstance(msgs, list) and len(msgs) > 0

Type guard

def has_messages(body: dict) -> bool:
    return isinstance(body.get('messages'), list) and len(body['messages']) > 0

Try / catch

try:
    resp = client.chat.completions.create(**body)
except openai.BadRequestError as e:
    if e.code == 'messages' or 'messages is required' in str(e):
        raise ValueError('Chat request built without messages; check message assembly')
    raise

Prevention

When it happens

Trigger: POST /v1/chat/completions with a body that has no 'messages' key, or where 'messages' was dropped by a serialization bug (e.g. sending {"model": "x", "prompt": "hi"} because the caller reused text-completions style params).

Common situations: Copy-pasting a /v1/completions curl example against /v1/chat/completions; a client library that only includes optional keys when non-empty and passing messages=None; JSON typos like 'message' or 'Messages'.

Related errors


AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15). Data as JSON: /api/errors/c1e342375e240db3. Report an issue: GitHub.