-
Notifications
You must be signed in to change notification settings - Fork 21.4k
Description
Checked other resources
- I added a very descriptive title to this issue.
- I searched the LangChain documentation with the integrated search.
- I used the GitHub search to find a similar question and didn't find it.
- I am sure that this is a bug in LangChain rather than my code.
Example Code
import operator
from langchain_core.utils.usage import _dict_int_op
from langchain_core.messages.ai import add_usage, UsageMetadata
# int values work fine
_dict_int_op({"a": 1}, {"a": 2}, operator.add) # ✅ {"a": 3}
# float values crash
_dict_int_op({"tokens": 10, "cost": 0.05}, {"tokens": 20, "cost": 0.03}, operator.add)
# ❌ ValueError: Unknown value types: [<class 'float'>]. Only dict and int values are supported.
# Real-world scenario: UsageMetadata with float total_cost
left = UsageMetadata(input_tokens=100, output_tokens=50, total_tokens=150)
left["total_cost"] = 0.005
right = UsageMetadata(input_tokens=200, output_tokens=100, total_tokens=300)
right["total_cost"] = 0.010
add_usage(left, right) # ❌ ValueErrorError Message and Stack Trace
ValueError: Unknown value types: [<class 'float'>]. Only dict and int values are supported.
Description
_dict_int_op() in libs/core/langchain_core/utils/usage.py only handles int and dict types but not float. When two dictionaries contain the same key with float values, the function raises a ValueError.
This affects streaming scenarios where LLM providers include float fields in UsageMetadata (e.g., total_cost, pricing fields, or any custom float metric). During chunk aggregation via add_usage() → _dict_int_op(), these float fields cause the aggregation to crash.
This is the same class of bug as #36011 (merge_dicts missing float support), but in a different function. The _dict_int_op function was designed to handle numeric operations on dictionaries but only checked for int, missing float.
All 4 float scenarios crash:
- Direct float values in dicts
- UsageMetadata with float
total_coston both sides - Float field present on only one side (default=0 is int, other side is float)
- Mixed int (from cache init
total_cost=0) + float (from providertotal_cost=0.005)
Root Cause
In usage.py, the type check is:
if isinstance(left.get(k, default), int) and isinstance(right.get(k, default), int):This should be:
if isinstance(left.get(k, default), (int, float)) and isinstance(right.get(k, default), (int, float)):Proposed Fix
- Change
isinstance(..., int)toisinstance(..., (int, float))in_dict_int_op() - Update docstring and error message to reflect float support
- Add regression tests for float values
System Info
langchain-core: 0.3.x (latest main)
Python: 3.10+
OS: macOS / Linux