Skip to content

fix: drop duplicate cache_read_input_token_cost_batches keys from the price maps - #42623

Merged
mateo-berri merged 1 commit into
mainfrom
litellm_fix_duplicate_cache_read_batches_keys
Sep 23, 2026
Merged

mateo-berri merged 1 commit into
mainfrom
litellm_fix_duplicate_cache_read_batches_keys

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Both price maps define cache_read_input_token_cost_batches twice in 23 entries
  • test_price_map_has_no_duplicate_keys fails on main for both files
  • Two PRs added the same key in different positions and git merged both copies

How it solves it:

  • Delete the second copy in each of the 23 entries, in both files
  • The two copies held equal values, so the parsed maps are unchanged
  • The existing schema test is the regression test and passes again

User Flow

Before: a contributor adding a model to the price map runs the schema test and it fails on entries they never touched

  1. They edit model_prices_and_context_window.json on a branch off main and run uv run pytest tests/test_litellm/test_model_prices_schema.py -k no_duplicate_keys
  2. test_price_map_has_no_duplicate_keys[main] and [backup] both fail with Left contains 23 more items, first extra item: 'cache_read_input_token_cost_batches'
  3. They open https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json and see gemini-3.5-flash listing cache_read_input_token_cost_batches twice with the same value, so nothing in their own change explains the red

After: the same test passes and the contributor only sees failures their own change causes

  1. They edit model_prices_and_context_window.json on a branch off main and run uv run pytest tests/test_litellm/test_model_prices_schema.py -k no_duplicate_keys
  2. test_price_map_has_no_duplicate_keys[main] and [backup] both pass
  3. https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json lists cache_read_input_token_cost_batches once per entry with the same values as before, so a proxy that fetches the map at boot prices batch cache reads exactly as it did

Relevant issues

Cleans up after #42543, #42557, and #42577, which each added the key to the same entries

Affected release

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Shared setup: every command runs from a BerriAI/litellm checkout. dupcount.py parses a price map from stdin with an object_pairs_hook and prints how many entries repeat a key:

import json
import sys
from collections import Counter

repeated = []


def hook(pairs):
    repeated.extend((key, n) for key, n in Counter(key for key, _ in pairs).items() if n > 1)
    return dict(pairs)


json.load(sys.stdin, object_pairs_hook=hook)
print(f"{len(repeated)} entries with a repeated key {sorted(set(repeated))}")

Before (7177d3b)

Schema test

  1. uv run pytest tests/test_litellm/test_model_prices_schema.py -k no_duplicate_keys -p no:cacheprovider --no-cov
  2. Output:
E       AssertionError: model_prices_and_context_window_backup.json defines the same key twice; JSON parsers keep only the last occurrence, so the earlier entry's fields are silently dropped. This is what a clean text merge of two branches that both added a model looks like: deduplicate the keys into one entry
E       assert ['cache_read_...batches', ...] == []
E         Left contains 23 more items, first extra item: 'cache_read_input_token_cost_batches'
tests/test_litellm/test_model_prices_schema.py:196: AssertionError
FAILED tests/test_litellm/test_model_prices_schema.py::test_price_map_has_no_duplicate_keys[backup]
FAILED tests/test_litellm/test_model_prices_schema.py::test_price_map_has_no_duplicate_keys[main]

Repeated keys in the published map

  1. curl -sSf https://raw.githubusercontent.com/BerriAI/litellm/7177d3b6d1/model_prices_and_context_window.json | python3 dupcount.py
  2. Output: 23 entries with a repeated key [('cache_read_input_token_cost_batches', 2)]
  3. git show 7177d3b6d1:litellm/model_prices_and_context_window_backup.json | python3 dupcount.py
  4. Output: 23 entries with a repeated key [('cache_read_input_token_cost_batches', 2)]
  5. The 23 entries, identical in both files: gemini-3-pro-image, gemini-3.1-flash-image, gemini-3.1-flash-lite-image, gemini-3.1-flash-lite, gemini-3.5-flash-lite, deep-research-pro-preview-12-2025, vertex_ai/gemini-3.5-flash, vertex_ai/gemini-3.6-flash, vertex_ai/gemini-3.7-flash, vertex_ai/gemini-3.8-flash, gemini-3.5-flash, gemini-3.6-flash, gemini-3.7-flash, gemini-3.8-flash, gpt-5-2025-08-07, gpt-5-mini-2025-08-07, gpt-5-nano-2025-08-07, vertex_ai/gemini-3-pro-image, vertex_ai/gemini-3.1-flash-image, vertex_ai/gemini-3.1-flash-lite-image, vertex_ai/gemini-3.1-flash-lite, vertex_ai/gemini-3.5-flash-lite, vertex_ai/deep-research-pro-preview-12-2025

Parsed maps unchanged

  1. Not applicable before the change, see After

Misc unit shard

  1. The Run tests step of _test-unit-base.yml with the misc shard's own test-path from test-unit.yml, MAX_FAILURES=10 WORKERS=2 RERUNS=2 TEST_TIMEOUT_SECONDS=120 DIST=loadscope, and the merge base's price maps: no tests ran in 36.46s, exit 0, because that test-path names directories that no longer exist
  2. The six tests that fail in the After run below, run on their own with the merge base's price maps checked out into the same tree (git checkout 7177d3b6d1 -- model_prices_and_context_window.json litellm/model_prices_and_context_window_backup.json): all six FAILED, the same way

After (d278ac1)

Schema test

  1. uv run pytest tests/test_litellm/test_model_prices_schema.py -k no_duplicate_keys -p no:cacheprovider --no-cov
  2. Output: 2 passed, 59 deselected in 0.20s

Repeated keys in the published map

  1. curl -sSf https://raw.githubusercontent.com/BerriAI/litellm/d278ac1561/model_prices_and_context_window.json | python3 dupcount.py
  2. Output: 0 entries with a repeated key []
  3. git show d278ac1561:litellm/model_prices_and_context_window_backup.json | python3 dupcount.py
  4. Output: 0 entries with a repeated key []
  5. python3 ci_cd/check_files_match.py prints Passed!, so the two files still match

Parsed maps unchanged

  1. For each of the two files: python3 -c "import json, subprocess; f = '<file>'; base = json.loads(subprocess.check_output(['git', 'show', '7177d3b6d1:' + f])); tip = json.loads(subprocess.check_output(['git', 'show', 'd278ac1561:' + f])); print(base == tip, len(base), base['gemini-3.5-flash']['cache_read_input_token_cost_batches'], tip['gemini-3.5-flash']['cache_read_input_token_cost_batches'])"
  2. Output for model_prices_and_context_window.json: True 4179 7.5e-08 7.5e-08
  3. Output for litellm/model_prices_and_context_window_backup.json: True 4179 7.5e-08 7.5e-08

Misc unit shard

  1. The same step with the misc shard's own test-path: no tests ran in 25.19s, exit 0, unchanged since the workflow file is identical at the merge base and the tip
  2. The same step over the shard's paths that exist, the filter ci(test-unit): drop dead misc shard paths and skip missing paths with a warning #42603 adds, with the same env: = 6 failed, 6520 passed, 21 skipped, 514 warnings, 11 rerun in 631.21s (0:10:31) =, exit 1
  3. Among the passes: PASSED tests/test_litellm/test_model_prices_schema.py::test_price_map_has_no_duplicate_keys[main] and PASSED tests/test_litellm/test_model_prices_schema.py::test_price_map_has_no_duplicate_keys[backup]
  4. The six failures fail identically with the merge base's price maps (item 2 of the Before case), so none comes from this PR: test_utils.py::test_aaamodel_prices_and_context_window_json_is_valid (fixed on main by test(utils): accept the per-size image cost keys in the price-map schema check #42612), test_cost_calculator.py::test_completion_cost_image_generation_registered_deployment_price_keeps_map_token_rates (fixed on main by test(cost_calculator): point image-generation deployment price test at a live gemini row #42615), test_router_per_deployment_num_retries.py::TestNoProviderRetryAmplification::test_direct_completion_still_forwards_num_retries_to_provider, test_redact_string_in_error_paths.py::TestOpenAIRealtimeRedaction::test_invalid_status_code_redacts_reason, test_redact_string_in_error_paths.py::TestAzureRealtimeRedaction::test_invalid_status_code_redacts_reason, and test_main.py::test_openai_env_base[OPENAI_API_BASE] (the four tracked in ci(test-unit): drop dead misc shard paths and skip missing paths with a warning #42603)

Type

🐛 Bug Fix

Caveats (if any)

Low

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Note

Low Risk
JSON-only deduplication with identical values; no runtime code changes and batch cache-read pricing behavior stays the same after parse.

Overview
Removes duplicate cache_read_input_token_cost_batches entries from 23 model blocks in model_prices_and_context_window.json and litellm/model_prices_and_context_window_backup.json. Each affected model (Gemini 3.x / Vertex variants, deep-research-pro-preview-12-2025, and several GPT-5 dated entries) had the key listed twice after overlapping PR merges; this keeps a single copy per model.

Parsed pricing is unchanged because both copies used the same values—this only restores valid JSON and makes test_price_map_has_no_duplicate_keys pass again on main and backup maps.

Reviewed by Cursor Bugbot for commit d278ac1. Bugbot is set up for automated code reviews on this repo. Configure here.

@devin-ai-integration

devin-ai-integration Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge because it removes only structurally duplicated pricing keys while preserving every effective value.

Summary

This PR removes redundant cache_read_input_token_cost_batches keys from 23 model records in both price maps.

  • Every removed key had an identical duplicate that remains in the same model record.
  • Effective pricing metadata is unchanged.
  • The primary and backup maps remain synchronized.

Reviews (1) · Last reviewed commit: "fix(pricing): drop the duplicate cache_r..."

@codspeed

codspeed Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_fix_duplicate_cache_read_batches_keys (d278ac1) with main (da82ea8)

Open in CodSpeed

@codecov

codecov Bot commented Sep 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit d278ac1. Configure here.

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mateo-berri
mateo-berri merged commit 7688f56 into main Sep 23, 2026
138 of 149 checks passed
@mateo-berri
mateo-berri deleted the litellm_fix_duplicate_cache_read_batches_keys branch September 23, 2026 00:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant