fix(auth): apply temp_budget_increase for cache-hit keys - #33841
Conversation
temp_budget_increase was only applied on the DB-fetch path of _user_api_key_auth_builder, so a key served from the auth cache reverted to its original max_budget and was wrongly blocked with BudgetExceededError once spend crossed the original budget while staying under the effective budget. Move _update_key_budget_with_temp_budget_increase out of the DB-only branch so it runs for every resolved token regardless of source. The cache stores the original budget and each cache hit returns a fresh model_copy(), so this never double-applies. Fixes #25760 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Greptile SummaryThis PR fixes a bug where
Confidence Score: 5/5Safe to merge — the change is a minimal, targeted relocation of a single function call from a DB-only branch to a shared branch, with no new logic introduced. The one-line move is correct: No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/auth/user_api_key_auth.py | Moves _update_key_budget_with_temp_budget_increase outside the DB-only branch so it executes for both cache-hit and DB-fetch paths; the change is minimal and correct. |
| tests/test_litellm/proxy/auth/test_user_api_key_auth.py | Adds a new regression test that seeds the auth cache with a key whose spend exceeds its original budget but falls under the effective budget after the temp increase, then drives it through the builder and asserts no exception and the correct resolved max_budget; all mocks, no real network calls. |
Reviews (1): Last reviewed commit: "fix(auth): apply temp_budget_increase fo..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
temp_budget_increase was only applied on the DB-fetch path of _user_api_key_auth_builder, so a key served from the auth cache reverted to its original max_budget and was wrongly blocked with BudgetExceededError once spend crossed the original budget while staying under the effective budget. Move _update_key_budget_with_temp_budget_increase out of the DB-only branch so it runs for every resolved token regardless of source. The cache stores the original budget and each cache hit returns a fresh model_copy(), so this never double-applies. Fixes #25760 Co-authored-by: shivam <shivam@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> (cherry picked from commit 089de50)
temp_budget_increase was only applied on the DB-fetch path of _user_api_key_auth_builder, so a key served from the auth cache reverted to its original max_budget and was wrongly blocked with BudgetExceededError once spend crossed the original budget while staying under the effective budget. Move _update_key_budget_with_temp_budget_increase out of the DB-only branch so it runs for every resolved token regardless of source. The cache stores the original budget and each cache hit returns a fresh model_copy(), so this never double-applies. Fixes BerriAI#25760 Co-authored-by: shivam <shivam@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> (cherry picked from commit 089de50)
Relevant issues
Fixes #25760
Linear ticket
Resolves LIT-4575
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Live proof against a local proxy (Postgres + Redis key-auth cache enabled, real
anthropic/claude-haiku-4-5calls costing real $). The same script is run twice against the same proxy config, once on pre-fix code and once with the fix, so the only variable is the one-line change. Unique prompts are used because identical prompts get served from the LLM response cache at $0 and never accumulate spend, which masks the repro. Spend propagation to the enforcement layer is async, so the block shows up after a short stream of requests rather than on the first over-budget oneCommands (same for both runs):
Before the fix (commit
fdf380d0e3, the fix reverted): once spend crosses the original budget, cache-hit requests are wrongly blocked at the originalMax budget: 0.0001even though current cost is far under the effective 100.0001After the fix (commit
af1ca72f1c): every request is allowed, spend reaches 0.002238 (over 22x the original 0.0001) while staying under the effective 100.0001Type
🐛 Bug Fix
Changes
temp_budget_increase(a temporary budget bump stored in a key's metadata) was only applied on the DB-fetch branch of_user_api_key_auth_builder. When the same key was served from the auth cache,_update_key_budget_with_temp_budget_increasenever ran, so the effectivemax_budgetreverted to the original low value and requests were wrongly blocked withBudgetExceededErroronce spend crossed the original budget while staying far under the effective budgetThe fix moves the call out of the
if valid_token is None:(DB-only) branch so it runs for every resolved token regardless of whether it came from cache or DBThis never double-applies: the cache stores the original budget (the increase is applied to the returned object, not the cached one) and each cache hit hands back a fresh
model_copy(), so the increase is recomputed per request from the originalmax_budgetRegression test
test_temp_budget_increase_applied_for_cached_keyseeds the auth cache with a key whose spend (5.0) exceeds its originalmax_budget(2.0) but stays under the effective budget (2.0 + 100.0), then drives the cache-hit request through_user_api_key_auth_builderand asserts it is not blocked and the resolved token carriesmax_budget == 102.0. It fails on the pre-fix code (raisesBudgetExceededError) and passes with the fixFinal Attestation
Link to Devin session: https://app.devin.ai/sessions/aa9a3156545a4d39b7b3ea9c2d204c6a
Requested by: @shivamrawat1