oobabooga/textgen · error · InvalidRequestError
messages: missing role
Error message
messages: missing role
What it means
Each element of the 'messages' array is validated to contain a 'role' key before processing. A message dict without 'role' raises InvalidRequestError (400, param='messages'). Roles are needed to apply the chat template correctly.
Source
Thrown at modules/api/completions.py:498
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')
if content is None:
# OpenAI allows content: null on assistant messages when tool_calls is present
if m['role'] == 'assistant' and m.get('tool_calls'):
m['content'] = ''
else:
raise InvalidRequestError(message="messages: missing content", param='messages')
# Validate multimodal content structure
if isinstance(content, list):
for item in content:
if not isinstance(item, dict) or 'type' not in item:
raise InvalidRequestError(message="messages: invalid content item format", param='messages')
if item['type'] not in ['text', 'image_url']:View on GitHub (pinned to ed888c71f2)
Solutions
- Ensure every message dict has a role: system | user | assistant | tool.
- Validate/normalize your messages array client-side before sending (see defense below).
- Log the exact payload on 400 to spot which element is malformed.
Example fix
# before
messages = [{"content": "hello"}]
# after
messages = [{"role": "user", "content": "hello"}] Defensive patterns
Strategy: validation
Validate before calling
def normalize_messages(messages):
out = []
for m in messages:
if 'role' not in m:
raise ValueError(f"message missing role: {m!r}")
out.append({'role': m['role'], 'content': m.get('content', '')})
return out Type guard
def is_valid_message(m) -> bool:
return isinstance(m, dict) and isinstance(m.get('role'), str) and m['role'] in {'system', 'user', 'assistant', 'tool'} Try / catch
try:
resp = client.chat.completions.create(model=m, messages=msgs)
except openai.BadRequestError as e:
if 'missing role' in str(e):
msgs = normalize_messages(msgs) # or fix the builder and re-raise
raise Prevention
- Always construct messages via a helper that takes (role, content).
- Validate every element with a type guard before sending.
- Never append partial dicts from template strings.
When it happens
Trigger: POST /v1/chat/completions where any element of messages lacks 'role', e.g. {"content": "hi"}, or is not a dict-shaped object with role (e.g. sending a bare string element that the framework wraps without a role).
Common situations: Building messages dynamically and forgetting to set the role; sending [{'user': 'text'}] instead of [{'role': 'user', 'content': 'text'}]; template string formatting bugs like '[{"role": "" + role + ""}]'.
Related errors
- messages: missing content
- functions is not supported.
- function_call is not supported.
- messages is required
- role: function is not supported.
AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15).
Data as JSON: /api/errors/fac0e1eac0f25639.
Report an issue: GitHub.