langchain - ✅(Solved) Fix bug(openai): _create_usage_metadata crashes with TypeError when service_tier is set and cached_tokens is missing [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langchain-ai/langchain#36657Fetched 2026-04-11 06:12:21
View on GitHub
Comments
1
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
labeled ×2commented ×1cross-referenced ×1

Error Message

from langchain_openai.chat_models.base import _create_usage_metadata

_create_usage_metadata( {"prompt_tokens": 100, "completion_tokens": 50, "total_tokens": 150, "prompt_tokens_details": {}, "completion_tokens_details": {}}, service_tier="priority" )

TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

Root Cause

The dict stores None for missing cached_tokens via .get("cached_tokens"), then .get(key, 0) returns None (not 0) because the key exists with value None. Same bug in _create_usage_metadata_responses.

Fix Action

Fix / Workaround

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • 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.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

PR fix notes

PR #36655: fix(openai): guard service_tier token arithmetic against None values

Description (problem / solution / changelog)

Bug

_create_usage_metadata and _create_usage_metadata_responses crash with:

TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

when service_tier is "priority" or "flex" and the OpenAI API response omits cached_tokens or reasoning_tokens from the token usage details.

Root Cause

The input_token_details dict is built with:

f"{service_tier_prefix}cache_read": (
    oai_token_usage.get("prompt_tokens_details") or {}
).get("cached_tokens"),  # ← None when key absent

This stores None as the value. The subsequent subtraction uses:

input_tokens - input_token_details.get(f"..._cache_read", 0)

dict.get(key, default) only returns the default when the key is missing. When the key exists with value None, the default is ignored and None is returned. int - NoneTypeError.

Reproduction

details = {"priority_cache_read": None}  # key exists, value None
100 - details.get("priority_cache_read", 0)
# TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

This triggers when a user has a priority/flex service tier and the API response's prompt_tokens_details does not include cached_tokens (or completion_tokens_details does not include reasoning_tokens).

Fix

Replace .get(key, 0) with .get(key) or 0 in all 4 affected sites (2 per function). or 0 coalesces both missing-key and present-but-None into 0.

# Before (crashes on None)
input_tokens - input_token_details.get(f"..._cache_read", 0)

# After (safe)
input_tokens - (input_token_details.get(f"..._cache_read") or 0)

Scope

  • _create_usage_metadata: 2 sites (cache_read + reasoning)
  • _create_usage_metadata_responses: 2 sites (same pattern)
  • 1 file changed, +15 -11

Related to #36500 which fixed a similar is-not-None pattern in other token extraction paths but did not cover the service_tier arithmetic.

Fixes #36657.

Changed files

  • libs/partners/openai/langchain_openai/chat_models/base.py (modified, +15/-11)

Code Example

from langchain_openai.chat_models.base import _create_usage_metadata

_create_usage_metadata(
    {"prompt_tokens": 100, "completion_tokens": 50, "total_tokens": 150,
     "prompt_tokens_details": {}, "completion_tokens_details": {}},
    service_tier="priority"
)
# TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'
RAW_BUFFERClick to expand / collapse

Checked other resources

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • 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.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package (Required)

langchain-openai

Describe the bug

Found this while reading the service_tier token arithmetic in _create_usage_metadata. When service_tier is "priority" or "flex" and the API response doesn't include cached_tokens in prompt_tokens_details, the subtraction crashes:

from langchain_openai.chat_models.base import _create_usage_metadata

_create_usage_metadata(
    {"prompt_tokens": 100, "completion_tokens": 50, "total_tokens": 150,
     "prompt_tokens_details": {}, "completion_tokens_details": {}},
    service_tier="priority"
)
# TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

The dict stores None for missing cached_tokens via .get("cached_tokens"), then .get(key, 0) returns None (not 0) because the key exists with value None. Same bug in _create_usage_metadata_responses.

Related to #36500 which fixed the same pattern in other token paths but missed the service_tier arithmetic.

System Info

langchain-openai 1.1.12, Python 3.12

extent analysis

TL;DR

The bug can be fixed by modifying the _create_usage_metadata function to handle the case where cached_tokens is None when calculating token arithmetic for "priority" or "flex" service tiers.

Guidance

  • The issue arises from the .get(key, 0) method returning None when the key exists with a value of None, causing a TypeError when trying to subtract None from an integer.
  • To fix this, the code should be modified to handle the case where cached_tokens is None, for example by using the .get() method with a default value of 0, or by explicitly checking for None before performing the subtraction.
  • The same fix should be applied to the _create_usage_metadata_responses function, which is also affected by this bug.
  • The fix should be verified by running the provided example code with the modified _create_usage_metadata function to ensure that it no longer raises a TypeError.

Example

def _create_usage_metadata(api_response, service_tier):
    # ...
    cached_tokens = api_response.get("prompt_tokens_details", {}).get("cached_tokens")
    if cached_tokens is None:
        cached_tokens = 0
    # ...

Notes

This fix assumes that a cached_tokens value of None should be treated as 0 for the purposes of token arithmetic. If this is not the case, the fix may need to be modified accordingly.

Recommendation

Apply workaround: the code should be modified to handle the case where cached_tokens is None to prevent the TypeError from occurring.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING