{"record":{"id":"fb33e6c362c62777","repo":"sgl-project/sglang","slug":"invalid-content-format-content-format","errorCode":null,"errorMessage":"Invalid content format: {content_format}","messagePattern":"Invalid content format: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/parser/jinja_template_utils.py","lineNumber":240,"sourceCode":"        return new_msg\n\n    elif content_format == \"string\":\n        # String format: flatten to text only (for templates like DeepSeek)\n        text_parts = []\n        for chunk in msg_dict[\"content\"]:\n            if isinstance(chunk, dict) and chunk.get(\"type\") in (\"text\", \"input_text\"):\n                text_parts.append(chunk[\"text\"])\n            # Note: For string format, we ignore images/audio since the template\n            # doesn't expect structured content - multimodal placeholders would\n            # need to be inserted differently\n\n        new_msg = msg_dict.copy()\n        new_msg[\"content\"] = \" \".join(text_parts) if text_parts else \"\"\n        new_msg = {k: v for k, v in new_msg.items() if v is not None}\n        return new_msg\n\n    else:\n        raise ValueError(f\"Invalid content format: {content_format}\")\n","sourceCodeStart":222,"sourceCodeEnd":241,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/parser/jinja_template_utils.py#L222-L241","documentation":"process_content_for_template_format dispatches on the shape of a message's content field (string, list-of-parts, etc.). This ValueError fires when content is a format the function has no branch for — typically a non-string, non-list type such as an int or dict.","triggerScenarios":"Passing a message dict where content is an integer, dict, or None in a path not covered, e.g. {'role': 'user', 'content': 42} into _apply_jinja_template.","commonSituations":"Clients sending numeric/boolean content (some APIs allow it), None content on tool-role messages, or malformed hand-crafted request bodies.","solutions":["Normalize content to a string or a list-of-parts list before applying the template","Validate incoming request bodies against the OpenAI chat schema (content must be string or array)","Convert non-string scalars with str(content) if your app allows them"],"exampleFix":"// before\nmessages = [{\"role\": \"user\", \"content\": 42}]\n// after\nmessages = [{\"role\": \"user\", \"content\": \"42\"}]","handlingStrategy":"validation","validationCode":"def content_ok(content):\n    return isinstance(content, (str, list)) and (not isinstance(content, list) or all(isinstance(p, dict) for p in content))\n\nfor m in messages:\n    if not content_ok(m.get(\"content\")):\n        m[\"content\"] = str(m.get(\"content\"))","typeGuard":"def is_valid_content(v: Any) -> TypeGuard[Union[str, list]]:\n    return isinstance(v, str) or (isinstance(v, list) and all(isinstance(p, dict) for p in v))","tryCatchPattern":"try:\n    rendered = _apply_jinja_template(messages, ...)\nexcept ValueError as e:\n    if \"Invalid content format\" in str(e):\n        messages = normalize_contents(messages); rendered = _apply_jinja_template(messages, ...)\n    else:\n        raise","preventionTips":["Validate request bodies against the OpenAI chat schema at the API edge","Coerce scalar content to str before template application","Reject or sanitize dict-shaped content early"],"tags":["jinja","chat-template","content-format","validation"],"backgroundTag":"invalid-message-content-format","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}