langchain-ai/langchain · error · ValueError
MESSAGE_COERCION_FAILURE
MESSAGE_COERCION_FAILURE
Error message
Unexpected message type: '{message_type}'. Use one of 'human', 'user', 'ai', 'assistant', 'function', 'tool', 'system', or 'developer'.
For troubleshooting, visit: https://docs.langchain.com/oss/python/langchain/errors/MESSAGE_COERCION_FAILURE What it means
Raised by `_create_message_from_message_type` (reached via `convert_to_messages`) when the message-type discriminator string is not one of 'human', 'user', 'ai', 'assistant', 'function', 'tool', 'system', 'developer', or 'remove'. It carries the `MESSAGE_COERCION_FAILURE` error code and a troubleshooting URL.
Source
Thrown at libs/core/langchain_core/messages/utils.py:680
kwargs["additional_kwargs"]["__openai_role__"] = "developer"
message = SystemMessage(content=content, **kwargs)
elif message_type == "function":
message = FunctionMessage(content=content, **kwargs)
elif message_type == "tool":
artifact = kwargs.get("additional_kwargs", {}).pop("artifact", None)
status = kwargs.get("additional_kwargs", {}).pop("status", None)
if status is not None:
kwargs["status"] = status
message = ToolMessage(content=content, artifact=artifact, **kwargs)
elif message_type == "remove":
message = RemoveMessage(**kwargs)
else:
msg = (
f"Unexpected message type: '{message_type}'. Use one of 'human',"
f" 'user', 'ai', 'assistant', 'function', 'tool', 'system', or 'developer'."
)
msg = create_message(message=msg, error_code=ErrorCode.MESSAGE_COERCION_FAILURE)
raise ValueError(msg)
return message
# Map of class names emitted in the `Serializable` constructor-envelope
# (`{"lc": 1, "type": "constructor", "id": [..., "<ClassName>"],
# "kwargs": {...}}`) to the message-type strings
# `_create_message_from_message_type` accepts. Read by
# `_convert_to_message`'s dict branch when unpacking that wire shape.
# Kept as a hardcoded allowlist of strings rather than a class registry
# lookup so dispatch never resolves to a class chosen by the caller.
_LC_CONSTRUCTOR_NAME_TO_TYPE: dict[str, str] = {
"HumanMessage": "human",
"HumanMessageChunk": "human",
"AIMessage": "ai",
"AIMessageChunk": "ai",
"SystemMessage": "system",
"SystemMessageChunk": "system",
"FunctionMessage": "function",View on GitHub (pinned to e32fa9a52e)
Solutions
- Map the role string to a supported one before conversion (see the supported list in the error message)
- Check for stray whitespace/case: use lowercase exact strings
- For new provider roles like 'developer', upgrade langchain-core to a version that supports them
Example fix
# before
convert_to_messages([{'type': 'tool_message', 'content': '42'}])
# after
convert_to_messages([{'type': 'tool', 'content': '42', 'tool_call_id': 'call_1'}]) Defensive patterns
Strategy: validation
Validate before calling
VALID_ROLES = {'human', 'user', 'ai', 'assistant', 'function', 'tool', 'system', 'developer', 'remove'}
def coerce_role(role: str) -> str:
aliases = {'tool_message': 'tool', 'bot': 'ai'}
r = role.strip().lower()
if r not in VALID_ROLES:
r = aliases.get(r, r)
assert r in VALID_ROLES, f'unknown role {role!r}'
return r Type guard
def is_valid_message_type(t: object) -> bool:
return isinstance(t, str) and t.strip().lower() in {
'human', 'user', 'ai', 'assistant', 'function', 'tool', 'system', 'developer', 'remove'} Try / catch
try:
msgs = convert_to_messages(raw)
except ValueError as e:
if 'MESSAGE_COERCION_FAILURE' in str(e) and 'Unexpected message type' in str(e):
raw = [(coerce_role(r), c) for r, c in raw]
msgs = convert_to_messages(raw)
else:
raise Prevention
- Map provider role names to langchain roles at ingestion time
- Trim/normalize role strings (case, whitespace) before conversion
- Upgrade langchain-core when adopting new provider roles like 'developer'
When it happens
Trigger: Passing tuples/dicts with an unknown role string, e.g. `('agent', 'hi')`, `{'type': 'bot', 'content': 'hi'}`, or an OpenAI role like 'tool_message' instead of 'tool'.
Common situations: Converting provider-specific histories (Bedrock/Anthropic/Gemini role names) without mapping to langchain roles; typos like 'assistance' or 'system '; roles added by a provider that langchain-core has not aliased yet.
Related errors
- Message as a sequence must be (role string, template)
- Invalid input type {type(model_input)}. Must be a PromptValu
- Received unsupported arguments {kwargs}
- Unsupported cache value {cache}
- Invalid input type {type(model_input)}. Must be a PromptValu
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/2d527ad476a16094.
Report an issue: GitHub.