{"record":{"id":"df7ad248dbce2851","repo":"langchain-ai/langchain","slug":"unknown-value-types-types-only-dict-and-int-va","errorCode":null,"errorMessage":"Unknown value types: {types}. Only dict and int values are supported.","messagePattern":"Unknown value types: (.+?)\\. Only dict and int values are supported\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/utils/usage.py","lineNumber":60,"sourceCode":"        if isinstance(left.get(k, default), int) and isinstance(\n            right.get(k, default), int\n        ):\n            combined[k] = op(left.get(k, default), right.get(k, default))\n        elif isinstance(left.get(k, {}), dict) and isinstance(right.get(k, {}), dict):\n            combined[k] = _dict_int_op(\n                left.get(k, {}),\n                right.get(k, {}),\n                op,\n                default=default,\n                depth=depth + 1,\n                max_depth=max_depth,\n            )\n        else:\n            types = [type(d[k]) for d in (left, right) if k in d]\n            msg = (\n                f\"Unknown value types: {types}. Only dict and int values are supported.\"\n            )\n            raise ValueError(msg)  # noqa: TRY004\n    return combined\n","sourceCodeStart":42,"sourceCodeEnd":62,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/utils/usage.py#L42-L62","documentation":"Raised by `_dict_int_op` in `langchain_core.utils.usage` when, while combining two usage-style dicts, a key's value in at least one dict is neither an `int` nor a `dict` (note `bool` counts as int; floats, strings, None, lists fail). The helper exists to sum integer counters (token counts), so any other type is rejected with `ValueError` listing the offending types.","triggerScenarios":"Aggregating token usage where one side carries a non-int value: `input_tokens: 12.0` (float), a provider-returned string count `\"12\"`, `None` from an optional field, or a list under a key that the other dict treats as int/dict. Also triggered by directly calling `_dict_int_op` with arbitrary payloads.","commonSituations":"Custom LLM providers returning numeric token counts as strings or floats; optional usage fields set to `None` when absent; merging usage dicts of different shapes across model versions; adding metadata (model name, cost as float) into the same dict that feeds usage accumulation.","solutions":["Normalize values to `int` before accumulating: `int(x)` for numeric strings/floats, drop or zero `None`.","Keep non-count metadata (model names, float costs) in a separate dict, not in the structure passed to usage accumulation.","Coerce provider responses in your integration's usage-extraction step so only `dict[str, int|dict]` reaches the combiner."],"exampleFix":"# before\nusage = {\"input_tokens\": \"128\", \"model\": \"gpt-4o\"}  # str + str metadata\n_dict_int_op(usage, other, operator.add)  # ValueError: Unknown value types\n\n# after\nusage = {\"input_tokens\": int(\"128\")}  # ints only; metadata kept elsewhere\n_dict_int_op(usage, other, operator.add)","handlingStrategy":"validation","validationCode":"def normalize_usage(d: dict) -> dict:\n    out = {}\n    for k, v in d.items():\n        if v is None:\n            continue\n        if isinstance(v, dict):\n            out[k] = normalize_usage(v)\n        elif isinstance(v, (int, float, str)) and not isinstance(v, bool):\n            out[k] = int(v)\n        else:\n            raise TypeError(f\"unsupported usage value {k}={v!r}\")\n    return out\n\nusage = normalize_usage(raw_provider_usage)  # now safe for _dict_int_op","typeGuard":"def is_int_dict(d: Any) -> TypeGuard[dict[str, int | dict]]:\n    return isinstance(d, dict) and all(\n        isinstance(v, (int, dict)) for v in d.values()\n    )","tryCatchPattern":"try:\n    total = _dict_int_op(left, right, operator.add)\nexcept ValueError as e:\n    logger.warning(\"skipping usage merge: %s\", e)\n    total = left","preventionTips":["Coerce provider counts to int at the integration boundary.","Keep metadata (names, float costs) out of usage-count dicts.","Reject None usage fields early (treat absent as 0)."],"tags":["usage","token-counting","type-mismatch"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}