{"record":{"id":"6e17ff0005013f51","repo":"oobabooga/textgen","slug":"messages-missing-content","errorCode":null,"errorMessage":"messages: missing content","messagePattern":"messages: missing content","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":400,"severity":"error","filePath":"modules/api/completions.py","lineNumber":509,"sourceCode":"    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']:\n                    raise InvalidRequestError(message=\"messages: unsupported content type\", param='messages')\n                if item['type'] == 'text' and 'text' not in item:\n                    raise InvalidRequestError(message=\"messages: missing text in content item\", param='messages')\n                if item['type'] == 'image_url' and ('image_url' not in item or 'url' not in item['image_url']):\n                    raise InvalidRequestError(message=\"messages: missing image_url in content item\", param='messages')\n\n    # Chat Completions\n    object_type = 'chat.completion' if not stream else 'chat.completion.chunk'\n    created_time = int(time.time())\n    cmpl_id = \"chatcmpl-%d\" % (int(time.time() * 1000000000))\n    resp_list = 'data' if is_legacy else 'choices'","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/api/completions.py#L491-L527","documentation":"Every message must have non-null 'content', except assistant messages that carry 'tool_calls' (OpenAI permits content:null there; the server coerces those to empty string). Any other message whose content is None (or absent) raises InvalidRequestError (400, param='messages').","triggerScenarios":"POST /v1/chat/completions with {\"role\": \"user\", \"content\": null}, a message dict that omits 'content', or an assistant tool-call message where content is null but 'tool_calls' is also missing/empty.","commonSituations":"Client code doing messages.append({\"role\": \"user\", \"content\": user_input}) with user_input=None; multimodal pipelines that null out content; sending an assistant message with tool_calls=[] (falsy) plus content:null, which fails the exception branch.","solutions":["Set content to a string (empty \"\" is acceptable) for every non-tool-call message.","For assistant tool-call messages, include a non-empty 'tool_calls' array if content is null, or just set content to ''.","Guard client-side: replace None content with '' before sending."],"exampleFix":"# before\nmessages.append({\"role\": \"user\", \"content\": None if not q else q})\n\n# after\nmessages.append({\"role\": \"user\", \"content\": q or \"\"})","handlingStrategy":"validation","validationCode":"def ensure_content(messages):\n    for m in messages:\n        if m.get('content') is None:\n            if m.get('role') == 'assistant' and m.get('tool_calls'):\n                m['content'] = ''\n            else:\n                m['content'] = ''  # or raise your own error before the API call\n    return messages","typeGuard":"def message_has_content(m) -> bool:\n    return m.get('content') is not None or (m.get('role') == 'assistant' and bool(m.get('tool_calls')))","tryCatchPattern":"try:\n    resp = client.chat.completions.create(model=m, messages=msgs)\nexcept openai.BadRequestError as e:\n    if 'missing content' in str(e):\n        msgs = ensure_content(msgs)\n        resp = client.chat.completions.create(model=m, messages=msgs)\n    else:\n        raise","preventionTips":["Default content to '' when user input may be None.","Keep tool_call_id-bearing assistant messages and their tool replies in pairs.","Validate with a type guard in your message-append helper."],"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"}