langchain-ai/langchain · error · TypeError
left and right are of different types. Left type: {type(lef
Error message
left and right are of different types. Left type: {type(left)}. Right type: {type(right)}. What it means
Raised by merge_dicts when left[key] and right[key] exist with different Python types — the per-key dispatch needs both sides to share a type to concatenate strings, merge dicts, or merge lists. This is the generic deep-merge utility behind prompt/data merging, not the message-chunk one. A type change on any shared key aborts the whole merge.
Source
Thrown at libs/core/langchain_core/utils/_merge.py:205
Args:
left: The first object to merge.
right: The other object to merge.
Returns:
The merged object.
Raises:
TypeError: If the key exists in both dictionaries but has a different type.
ValueError: If the two objects cannot be merged.
"""
if left is None or right is None:
return left if left is not None else right
if type(left) is not type(right):
msg = (
f"left and right are of different types. Left type: {type(left)}. Right "
f"type: {type(right)}."
)
raise TypeError(msg)
if isinstance(left, str):
return left + right
if isinstance(left, dict):
return merge_dicts(left, right)
if isinstance(left, list):
return merge_lists(left, right)
if left == right:
return left
msg = (
f"Unable to merge {left=} and {right=}. Both must be of type str, dict, or "
f"list, or else be two equal objects."
)
raise ValueError(msg)
View on GitHub (pinned to e32fa9a52e)
Solutions
- Normalize both sides to the same type for shared keys before calling merge_dicts (e.g. wrap scalars in a list)
- Restructure so the conflicting key is not present on both sides — pop it from one
- Validate inputs upstream with a schema (pydantic) so type drift is caught with a clearer error
- Catch TypeError and apply an explicit per-key resolution policy for known-volatile keys
Example fix
# before
from langchain_core.utils import merge_dicts
merged = merge_dicts({"docs": "a b"}, {"docs": ["a", "b"]}) # TypeError
# after
left = {"docs": ["a b"]}
merged = merge_dicts(left, {"docs": ["a", "b"]}) # list + list merges Defensive patterns
Strategy: type-guard
Validate before calling
shared = set(left) & set(right)
for k in shared:
if type(left[k]) is not type(right[k]):
msg = f"key {k!r}: {type(left[k]).__name__} vs {type(right[k]).__name__}"
raise TypeError(msg) # clearer than the library's message Type guard
from typing import Any
def dict_types_compatible(left: dict[str, Any], right: dict[str, Any]) -> bool:
return all(
type(left[k]) is type(right[k])
for k in set(left) & set(right)
) Prevention
- Normalize shared keys to one type (usually list) before deep-merging
- Build prompt/example dicts from pydantic models so types are fixed
- Add a pre-merge type check in test fixtures for merged configurations
When it happens
Trigger: merge_dicts({'a': 'x'}, {'a': ['x']}); merging template partials where one side supplies a string and the other a list for the same variable; merging config/data dicts assembled from JSON sources with schema drift; example_prompt kwargs built from mixed sources.
Common situations: Prompt templates with partial variables whose type differs between code defaults and runtime inputs; merging serialized examples where a field changed type between versions; dataclass/to-dict conversions producing lists vs scalars for the same field.
Related errors
- maxsize must be greater than 0
- Could not resolve content_key {full_path!r}: expected a mapp
- Could not resolve content_key {full_path!r}: missing key {ke
- Unable to get string for blob {self}
- Unable to get bytes for blob {self}
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/0fa4229c656e8735.
Report an issue: GitHub.