sgl-project/sglang · error · ValueError
'role' must be a string
Error message
'role' must be a string
What it means
The role field must be a string; passing an int, dict, list, or None triggers ValueError during normalization.
Source
Thrown at python/sglang/srt/entrypoints/openai/protocol.py:709
content: Union[str, List[ChatCompletionMessageContentPart], None] = Field(
default=None
)
tool_call_id: Optional[str] = None
name: Optional[str] = None
reasoning_content: Optional[str] = None
tool_calls: Optional[List[ToolCall]] = Field(default=None, examples=[None])
tools: Optional[List[Tool]] = Field(default=None, examples=[None])
@field_validator("role", mode="before")
@classmethod
def _normalize_role(cls, v):
if isinstance(v, str):
v_lower = v.lower()
if v_lower not in _GENERIC_MESSAGE_ROLES:
allowed = ", ".join(repr(r) for r in _GENERIC_MESSAGE_ROLES)
raise ValueError(f"'role' must be one of {allowed} (case-insensitive).")
return v_lower
raise ValueError("'role' must be a string")
@model_validator(mode="after")
def validate_thinking_parts_role(self):
if self.role != "assistant" and isinstance(self.content, list):
for part in self.content:
if isinstance(part, ChatCompletionMessageContentThinkingPart):
raise ValueError(
"thinking content parts are only valid in assistant messages"
)
return self
class ChatCompletionMessageUserParam(BaseModel):
role: Literal["user"]
content: Union[str, List[ChatCompletionMessageContentPart]]
@model_validator(mode="after")
def validate_thinking_parts_role(self):View on GitHub (pinned to 0132848349)
Solutions
- Ensure role is a plain string like 'user'.
- Add client-side typing/schema validation for messages before the request.
Example fix
# before
{"role": 1, "content":"hi"}
# after
{"role": "user", "content":"hi"} Defensive patterns
Strategy: type-guard
Validate before calling
assert all(isinstance(m.get('role'),str) for m in messages) Type guard
def role_is_string(m): return isinstance(m.get('role'),str) Prevention
- Type-check message dicts in test fixtures.
When it happens
Trigger: messages=[{'role': 1, ...}], role=None, or role={'name':'user'} in the request body.
Common situations: Programmatic message construction with wrong types; JSON where role was a number; dict unpacking mistakes.
Related errors
- 'role' must be one of {allowed} (case-insensitive).
- reasoning_effort must not be a boolean
- spt must be a bool when provided
- Unknown type: {type(other)}
- Invalid value: {other}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/3aca2fafc77ba7f9.
Report an issue: GitHub.