sgl-project/sglang · error · ValueError
The system message should be a single text.
Error message
The system message should be a single text.
What it means
A system message whose content is a list must contain exactly one part of type 'text'. If the list is empty, has more than one element, or its first element's type is not 'text' (e.g. 'image_url'), generate_chat_conv raises this ValueError.
Source
Thrown at python/sglang/srt/parser/conversation.py:640
image_token=conv.image_token,
audio_token=conv.audio_token,
video_token=conv.video_token,
image_token_at_prefix=conv.image_token_at_prefix,
)
if isinstance(request.messages, str):
raise ValueError("The messages should be a list of dict.")
for message in request.messages:
msg_role = message.role
if msg_role == "system":
if isinstance(message.content, str):
conv.system_message = message.content
elif isinstance(message.content, list):
if (
len(message.content) != 1
or getattr(message.content[0], "type", None) != "text"
):
raise ValueError("The system message should be a single text.")
else:
conv.system_message = getattr(message.content[0], "text", "")
elif msg_role == "user":
# Handle the various types of Chat Request content types here.
if isinstance(message.content, str):
conv.append_message(conv.roles[0], message.content)
else:
real_content = ""
# calculate number of image_url
num_image_url = 0
for content in message.content:
if content.type == "image_url":
num_image_url += 1
conv.modalities.append(content.modalities)
image_token = (
conv.image_token + "\n"
if conv.name not in ("qwen2-vl", "moss-vl", "unlimited-ocr")
else conv.image_tokenView on GitHub (pinned to 0132848349)
Solutions
- Make the system message content a plain string: "content": "You are helpful"
- If using a list, keep exactly one part with "type":"text"
- Move images to a user message — system role cannot carry multimodal content
Example fix
# before
{"role":"system","content":[{"type":"text","text":"a"},{"type":"text","text":"b"}]}
# after
{"role":"system","content":"You are helpful"} Defensive patterns
Strategy: type-guard
Validate before calling
for m in messages:
if m["role"] == "system" and isinstance(m["content"], list):
assert len(m["content"]) == 1 and m["content"][0].get("type") == "text" Type guard
def ok_system(c): return isinstance(c, str) or (isinstance(c, list) and len(c)==1 and isinstance(c[0], dict) and c[0].get("type")=="text") Prevention
- Prefer plain-string system messages
- Never attach images to the system role
When it happens
Trigger: Sending messages=[{"role":"system","content":[{"type":"image_url",...}]}, ...] or a system message with content=[{"type":"text",...},{"type":"text",...}] (two parts).
Common situations: Copying multimodal user-message formatting into the system role; frontends that always wrap content in a parts list.
Related errors
- The assistant's response should be a single text.
- v_cache must be provided
- q can only be None when only_qv=True
- q must be provided unless qv is provided with only_qv=True
- `dt_bias` must have {HV * K} elements (got {dt_bias.numel()}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/a72d75672e8a8f69.
Report an issue: GitHub.