{"record":{"id":"016a31b4b9e461a7","repo":"oobabooga/textgen","slug":"messages-invalid-content-item-format","errorCode":null,"errorMessage":"messages: invalid content item format","messagePattern":"messages: invalid content item format","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":400,"severity":"error","filePath":"modules/api/completions.py","lineNumber":515,"sourceCode":"        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'\n\n    # generation parameters\n    generate_params = process_parameters(body, is_legacy=is_legacy)\n    if stop_event is not None:\n        generate_params['stop_event'] = stop_event\n    continue_ = body['continue_']","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/api/completions.py#L497-L533","documentation":"When a message's 'content' is a list (multimodal OpenAI format), each item must be a dict containing a 'type' key. Items that are not dicts, or dicts without 'type', raise InvalidRequestError (400, param='messages') before the content is flattened for the model.","triggerScenarios":"POST /v1/chat/completions with {\"role\": \"user\", \"content\": [\"hello\"]} (bare string item) or {\"role\": \"user\", \"content\": [{\"text\": \"hello\"}]} (missing 'type').","commonSituations":"Hand-building multimodal arrays and forgetting the {'type': 'text', ...} wrapper; mixing OpenAI vision format with Anthropic/Llama-style content blocks; old client libs that emitted text-only arrays.","solutions":["Wrap every list item with an explicit type: {\"type\": \"text\", \"text\": ...} or {\"type\": \"image_url\", \"image_url\": {\"url\": ...}}.","For plain text, prefer a string content instead of a single-element list.","Validate content-list shape client-side before sending."],"exampleFix":"# before\n{\"role\": \"user\", \"content\": [\"describe this\", {\"image_url\": {\"url\": u}}]}\n\n# after\n{\"role\": \"user\", \"content\": [{\"type\": \"text\", \"text\": \"describe this\"}, {\"type\": \"image_url\", \"image_url\": {\"url\": u}}]}","handlingStrategy":"validation","validationCode":"def valid_content_items(content: list) -> bool:\n    return all(isinstance(i, dict) and isinstance(i.get('type'), str) for i in content)","typeGuard":"def is_content_item(i) -> bool:\n    return isinstance(i, dict) and 'type' in i and i['type'] in ('text', 'image_url')","tryCatchPattern":"try:\n    resp = client.chat.completions.create(model=m, messages=msgs)\nexcept openai.BadRequestError as e:\n    if 'invalid content item format' in str(e):\n        msgs = [{'role': m['role'], 'content': repair_items(m['content']) if isinstance(m.get('content'), list) else m.get('content', '')} for m in msgs]\n        resp = client.chat.completions.create(model=m, messages=msgs)\n    else:\n        raise","preventionTips":["Build multimodal items only through a helper that always sets 'type'.","Send plain strings for text-only messages instead of one-element lists.","Lint every content list element with a type guard before the request."],"tags":["openai-api","chat-completions","multimodal","validation"],"backgroundTag":null,"analyzedSha":"ed888c71f221df552750e1834b3654abab8ae345","analyzedAt":"2026-08-15T05:24:21.000Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}