litellm/tests/test_litellm/router_utils
runjivu 4a70bc3ba3 fix: re-check budget on router fallback targets
Budget is enforced once during auth, against the requested model group.
`_is_model_cost_zero` waives every budget check for a zero-cost group, and the
router then picks a fallback target afterwards, inside `run_async_fallback`,
where nothing re-checks budget. A free model with a paid fallback therefore
bills with no budget gate at all.

Add `fallback_budget_check`, the budget sibling of the existing
`fallback_access_check`: a predicate awaited per fallback target that skips
targets the caller cannot pay for. The primary attempt is untouched, so a
zero-cost model is never blocked by budget and only the paid fallback is
refused.

Counter reads pass `max_budget` so `get_current_spend` verifies against
authoritative recorded spend, matching the auth-time key and user checks; a
counter restored from an older snapshot reads as a hit rather than a clean
miss, so without it a stale-low value would keep admitting paid fallbacks.

A zero-cost fallback target is always allowed, and a team key does not inherit
the key owner's personal budget unless `apply_user_budget_to_team_keys` is set,
matching `_PROXY_MaxBudgetLimiter`.

Scope is key and user budgets. Team, team-member, end-user, org, global and
per-model budgets are not covered yet: those auth-path functions enforce rather
than report, so reusing them would fire threshold alerts and take spend
reservations for a target that is then skipped. Two limitations of that scope
are documented in the module docstring: the check reads the spend counter
rather than reserving against it, so concurrent fallbacks can cross a cap
together; and a request reaching the router without
`metadata["user_api_key_auth"]` is not restricted. Both are shared with
`fallback_model_access.py`.

Opt-in via `general_settings.enforce_fallback_budget`.

Relates to #41344

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 19:06:38 +09:00
..
pre_call_checks Merge pull request #41174 from BerriAI/litellm_tier_model_affinity 2026-09-15 09:54:53 -07:00
test_add_retry_fallback_headers.py feat(proxy): expose complexity routing headers (#40792) 2026-09-11 17:14:40 -07:00
test_auto_router_model_naming.py feat(router): apply entitlement limits to forecast classifiers 2026-09-15 16:17:00 -07:00
test_auto_router_tuning_baseline.py feat(complexity_router): rebalance heuristic weights in the dashboard and grade custom dimensions by match count (#40205) 2026-09-08 13:28:57 -07:00
test_cooldown_cache.py fix(router): give cooldowns their own cache so siblings see a bench in ~1s (#40025) 2026-09-08 10:11:20 -07:00
test_cooldown_handlers.py test(router): annotate return types of team cooldown test helpers 2026-09-13 09:50:12 +00:00
test_fallback_event_handlers.py fix: re-check budget on router fallback targets 2026-09-16 19:06:38 +09:00
test_get_retry_from_policy.py refactor(router): resolve retry policy by exception MRO and add DefaultRetries 2026-09-04 16:09:01 -07:00
test_health_check_allowed_fails_integration.py fix(router): count allowed_fails in the shared router cache so multi-worker proxies bench a deployment fleet-wide (#40224) 2026-09-08 13:54:48 -07:00
test_health_state_cache.py fix(router): treat a breaker-refused Redis read as a miss in the health state cache 2026-09-10 18:16:59 -07:00
test_pattern_match_deployments.py fix(proxy): make the invalid-model 403 path cheap under a burst of rejections (#39892) 2026-09-05 11:53:04 -07:00
test_reasoning_effort_capability.py fix(cost-map): stop advertising reasoning_effort max on the azure gpt-6-astra rows 2026-09-05 22:31:32 -07:00
test_router_health_check_routing.py feat(health): opt-in model-group allowlist for background health checks and health-check routing (#38539) 2026-08-27 12:25:56 -07:00
test_router_interactions_endpoints.py Gemini managed agents support (#28270) 2026-05-19 16:02:03 -07:00
test_router_utils_common_utils.py fix(router): keep a model's own provider prefix for generic SDK calls 2026-09-04 23:32:26 -07:00