langchain · difficulty ◆◆
_convert_to_message and the Constructor-Envelope Wire Shape
Round-trip your serialized messages without the cryptic ValueError.
Messages are the currency of every chain. Learn the one wire shape that used to break the round-trip and how 1.4.1 finally fixes it.
$ pip install -U langchain-core>=1.4.1What it does
_convert_to_message is an internal LangChain core helper that turns raw API output (like an LLM response chunk) into a proper Message object: AIMessage, HumanMessage, SystemMessage, or ToolMessage. In langchain-core==1.4.1 a bug was fixed where messages serialized with LangChain’s own Serializable envelope format (the id, type, data wire shape) could not be correctly round-tripped back through this function. Before, only plain dict shapes were accepted; now both the native wire format and LangChain’s own constructor envelope work.
Why it matters
Anyone building pipelines that serialize and deserialize messages is affected: caching LLM responses to a database, passing messages across process boundaries, or replaying conversation history. Before the fix, a message saved using LangChain’s own serialization would fail to load when replayed, causing cryptic ValueError or AttributeError exceptions. This was especially painful with tool-augmented chains where AIMessage.tool_calls and ToolMessage objects are interleaved. After the fix, the full round-trip works reliably.
Example
$ Envelope round-trip demoType: AIMessage
Content: The capital of France is Paris.
ID: msg-001
Tool calls after round-trip: [{'name': 'search', 'args': {'query': 'capital of France'}, 'id': 'call-abc123'}]The envelope_payload dict with id, type=constructor and data is now handled directly by _convert_to_message.
$ Serialize then restore via to_dictHello, world!
weatherUse convert_to_messages([json.loads(serialized)]) and preserve tool_calls through the round-trip.
Common flags
- --constructor-envelope
- Accept the id/type/data Serializable wire shape when converting to a message
- --plain-dict
- Legacy plain-dict shapes continue to be accepted for backwards compatibility
History
Origin
langchain-core==1.4.1 (published June 5, 2026) carried the fix; the changelog landed on June 8 via GitHub PR #37456.
Evolution
Earlier versions only handled plain dict payloads. The 1.4.1 fix teaches _convert_to_message to recognize LangChain’s own Serializable constructor-envelope wire format so internally-produced serializations load cleanly.
Fun facts
Pros & cons
pros
- + Reliable message persistence
- + Tool calls survive serialization
- + Backwards compatible with plain dicts
cons
- − Internal API, not a public contract
- − Requires upgrading core to >=1.4.1
Takeaways
- 1Use convert_to_messages to rebuild Message objects from serialized dicts.
- 2Upgrade langchain-core to >=1.4.1 to fix constructor-envelope round-tripping.
- 3Tool calls (AIMessage.tool_calls) now survive the round-trip cleanly.