OpenBMB/ChatDev · error · ValueError
message dict missing role
Error message
message dict missing role
What it means
Message.from_dict requires a truthy 'role' key; a dict without role (or with role: null/"") raises ValueError. The role is then fed to MessageRole(role_value), so an unknown role string raises ValueError from the enum instead.
Source
Thrown at entity/messages.py:350
if self.name:
payload["name"] = self.name
if self.tool_call_id:
payload["tool_call_id"] = self.tool_call_id
if self.metadata:
payload["metadata"] = self.metadata
if self.tool_calls:
payload["tool_calls"] = [call.to_openai_dict() for call in self.tool_calls]
if self.keep:
payload["keep"] = self.keep
if self.preserve_role:
payload["preserve_role"] = self.preserve_role
return payload
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Message":
role_value = data.get("role")
if not role_value:
raise ValueError("message dict missing role")
role = MessageRole(role_value)
content = data.get("content")
if isinstance(content, list):
converted: List[MessageBlock] = []
for block in content:
if isinstance(block, MessageBlock):
converted.append(block)
elif isinstance(block, dict):
try:
converted.append(MessageBlock.from_dict(block))
except Exception:
# Preserve raw dict for debugging; text_content will stringify best-effort
converted.append(
MessageBlock(
type=MessageBlockType.DATA,
text=str(block),
data=block,
)View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Include a valid role key: "role": "user" (or assistant/system/tool per MessageRole)
- If the dict may be incomplete, guard with item.get("role") checks before calling from_dict
- Regenerate/re-fetch the source JSON if a writer dropped the field
Example fix
// before
Message.from_dict({"content": "hi"})
// after
Message.from_dict({"role": "user", "content": "hi"}) Defensive patterns
Strategy: type-guard
Validate before calling
if not item.get("role"):
item["role"] = "user" # or skip/reject the record Type guard
def is_valid_message_dict(d) -> bool:
roles = {"system", "user", "assistant", "tool"}
return isinstance(d, dict) and d.get("role") in roles Try / catch
try:
msg = Message.from_dict(item)
except ValueError:
log.warning("dropping malformed message: %r", item) Prevention
- Always emit role when serializing messages
- Validate external/LLM-produced dicts before from_dict
When it happens
Trigger: Message.from_dict({"content": "hi"}); deserializing partial/stripped JSON where role was dropped; role: "" from template rendering.
Common situations: Persisted message JSON mutated downstream; LLM tool output misshapoen dicts; hand-building dicts for tests and forgetting role.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- message payload must be a list
- No node types registered; cannot validate workflow
- Unsupported node type '{ntype}' for node '{nid}'. Only {allo
- Design file not found: {config_path}
- YAML root must be a mapping
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/31d96c6b1ff5df9a.
Report an issue: GitHub.