langchain-ai/langchain · error · ValueError
Got unexpected message type: {type_}
Error message
Got unexpected message type: {type_} What it means
Raised by the internal message-deserialization dispatch (used by `messages_from_dict`) when the 'type' string of a serialized message does not match any known class name ('HumanMessage', 'AIMessageChunk', 'ToolMessageChunk', etc.). The deserializer only instantiates from a fixed allowlist of type strings.
Source
Thrown at libs/core/langchain_core/messages/utils.py:544
return FunctionMessage(**message["data"])
if type_ == "tool":
return ToolMessage(**message["data"])
if type_ == "remove":
return RemoveMessage(**message["data"])
if type_ == "AIMessageChunk":
return AIMessageChunk(**message["data"])
if type_ == "HumanMessageChunk":
return HumanMessageChunk(**message["data"])
if type_ == "FunctionMessageChunk":
return FunctionMessageChunk(**message["data"])
if type_ == "ToolMessageChunk":
return ToolMessageChunk(**message["data"])
if type_ == "SystemMessageChunk":
return SystemMessageChunk(**message["data"])
if type_ == "ChatMessageChunk":
return ChatMessageChunk(**message["data"])
msg = f"Got unexpected message type: {type_}"
raise ValueError(msg)
def messages_from_dict(messages: Sequence[dict[str, Any]]) -> list[BaseMessage]:
"""Convert a sequence of messages from dicts to `Message` objects.
Args:
messages: Sequence of messages (as dicts) to convert.
Returns:
list of messages (BaseMessages).
"""
return [_message_from_dict(m) for m in messages]
def message_chunk_to_message(chunk: BaseMessage) -> BaseMessage:
"""Convert a message chunk to a `Message`.
View on GitHub (pinned to e32fa9a52e)
Solutions
- Check the exact 'type' spelling against the supported list (HumanMessage, AIMessage, SystemMessage, FunctionMessage, ToolMessage, ChatMessage and their Chunk variants)
- If data comes from another version, map/normalize type strings before deserializing
- Re-serialize messages with the current langchain-core version so type names match
Example fix
# before
messages_from_dict([{'type': 'human_message', 'data': {'content': 'hi'}}])
# after
messages_from_dict([{'type': 'HumanMessage', 'data': {'content': 'hi', 'type': 'human'}}]) Defensive patterns
Strategy: validation
Validate before calling
KNOWN_TYPES = {'HumanMessage', 'AIMessage', 'SystemMessage', 'FunctionMessage',
'ToolMessage', 'ChatMessage', 'AIMessageChunk', 'HumanMessageChunk',
'FunctionMessageChunk', 'ToolMessageChunk', 'SystemMessageChunk', 'ChatMessageChunk'}
def deserializable(d: dict) -> bool:
return d.get('type') in KNOWN_TYPES Type guard
def is_known_serialized_type(d: dict) -> bool:
return isinstance(d, dict) and d.get('type') in KNOWN_TYPES Try / catch
try:
msgs = messages_from_dict(data)
except ValueError as e:
if 'unexpected message type' in str(e):
data = normalize_type_strings(data) # map old/misspelled names
msgs = messages_from_dict(data)
else:
raise Prevention
- Persist messages with the same langchain-core version that will read them
- Normalize type strings after cross-version data migration
- Round-trip test serialization/deserialization for custom persisted formats
When it happens
Trigger: Calling `messages_from_dict` on dicts whose 'type' field is a misspelled or unknown class name, e.g. `{'type': 'humanmessage', 'data': {...}}` or a type from a newer/older langchain version.
Common situations: Loading chat histories persisted by a different langchain-core version that serialized a class name this version dropped or renamed; hand-edited JSON logs; cross-system message exchange where one side uses non-standard type strings.
Related errors
- {save_path} must be json or yaml
- Trying to load an object that doesn't implement serializatio
- Failed to hash metadata: {e}. Please use a dict that can be
- Expected Serializable, got {type(obj)}
- `default` should not be passed to dumps
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/d1ddb9552ad9f526.
Report an issue: GitHub.