{"record":{"id":"fac0e1eac0f25639","repo":"oobabooga/textgen","slug":"messages-missing-role","errorCode":null,"errorMessage":"messages: missing role","messagePattern":"messages: missing role","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":400,"severity":"error","filePath":"modules/api/completions.py","lineNumber":498,"sourceCode":"\n    if body.get('function_call', ''):\n        raise InvalidRequestError(message=\"function_call is not supported.\", param='function_call')\n\n    if 'messages' not in body:\n        raise InvalidRequestError(message=\"messages is required\", param='messages')\n\n    tools = None\n    if 'tools' in body and body['tools'] is not None and isinstance(body['tools'], list) and body['tools']:\n        tools = validateTools(body['tools'])  # raises InvalidRequestError if validation fails\n\n    tool_choice = body.get('tool_choice', None)\n    if tool_choice == \"none\":\n        tools = None  # Disable tool detection entirely\n\n    messages = body['messages']\n    for m in messages:\n        if 'role' not in m:\n            raise InvalidRequestError(message=\"messages: missing role\", param='messages')\n        elif m['role'] == 'function':\n            raise InvalidRequestError(message=\"role: function is not supported.\", param='messages')\n\n        # Handle multimodal content validation\n        content = m.get('content')\n        if content is None:\n            # OpenAI allows content: null on assistant messages when tool_calls is present\n            if m['role'] == 'assistant' and m.get('tool_calls'):\n                m['content'] = ''\n            else:\n                raise InvalidRequestError(message=\"messages: missing content\", param='messages')\n\n        # Validate multimodal content structure\n        if isinstance(content, list):\n            for item in content:\n                if not isinstance(item, dict) or 'type' not in item:\n                    raise InvalidRequestError(message=\"messages: invalid content item format\", param='messages')\n                if item['type'] not in ['text', 'image_url']:","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/api/completions.py#L480-L516","documentation":"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.","triggerScenarios":"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).","commonSituations":"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 + \"\"}]'.","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."],"exampleFix":"# before\nmessages = [{\"content\": \"hello\"}]\n\n# after\nmessages = [{\"role\": \"user\", \"content\": \"hello\"}]","handlingStrategy":"validation","validationCode":"def normalize_messages(messages):\n    out = []\n    for m in messages:\n        if 'role' not in m:\n            raise ValueError(f\"message missing role: {m!r}\")\n        out.append({'role': m['role'], 'content': m.get('content', '')})\n    return out","typeGuard":"def is_valid_message(m) -> bool:\n    return isinstance(m, dict) and isinstance(m.get('role'), str) and m['role'] in {'system', 'user', 'assistant', 'tool'}","tryCatchPattern":"try:\n    resp = client.chat.completions.create(model=m, messages=msgs)\nexcept openai.BadRequestError as e:\n    if 'missing role' in str(e):\n        msgs = normalize_messages(msgs)  # or fix the builder and re-raise\n    raise","preventionTips":["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."],"tags":["openai-api","chat-completions","messages","validation"],"backgroundTag":null,"analyzedSha":"ed888c71f221df552750e1834b3654abab8ae345","analyzedAt":"2026-08-15T05:24:21.000Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}