litellm/tests/unit/test_router
norkelbyte 85a3e566f3
fix(router)!: name the request size when usage-based routing refuses an over-tpm request (#51838)
* fix(router)!: name the request size when usage-based routing refuses an over-tpm request

usage-based-routing-v2 answered "No deployments available" with no usage
shown when one request alone was over every deployment's tpm, and a
single-deployment group held the caller for 3 x 60 seconds on retries
that could never clear it.

The router now raises RequestOverDeploymentTpmError, a RateLimitError
that names the estimated tokens and the largest tpm limit, carries no
retry-after, skips retries, and still reaches group fallbacks.

* fix(router): count cooling deployments before refusing an over-tpm request, keep the Prometheus label

The over-tpm refusal now also reads every deployment in the model group, so a request that fits a cooling deployment keeps the old retryable 429. RequestOverDeploymentTpmError keeps the RateLimitError exception_class label in Prometheus.

* fix(router): count only cooling deployments the request can still reach, and keep the logged error class

The over-tpm refusal now reads cooling deployments from the caller's pool, kept to the ones team, region, and tag routing would still send the request to, so team models and tag-filtered requests get the right answer. Logs, OTEL, and Datadog keep naming the refusal RateLimitError like Prometheus does, and a tpm written as a number string counts as that number

* fix(router): keep the sync over-tpm refusal a ValueError and count every deployment the caller may use

The sync Router raises SyncRequestOverDeploymentTpmError, which is still a ValueError, so
existing except ValueError handlers keep catching it. The never-retryable refusal now counts
every deployment in the caller's pool that region and tag routing allow, so a deployment left
out of this pick by a budget, health check, order, or pin keeps the retryable 429

* fix(router): keep retry records and trace events naming the over-tpm refusal RateLimitError

Fallback records in previous_models and the litellm.routing.retry trace event now read the
error's logged class name, as the logging payload already did, so they keep RateLimitError for
the over-tpm refusal as they did before this change

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-11-14 16:16:21 -05:00
..
core fix(responses): accept a string or tuple allowed_openai_params on Responses models instead of answering 500 (#51751) 2026-11-14 04:32:38 -05:00
__init__.py test: add __init__.py to every tests/unit directory phase 16 touches 2026-09-20 11:52:38 +00:00
test_enforce_model_rate_limits.py refactor(router): count the whole router_usage family on the native store (#50862) 2026-11-13 03:22:28 +00:00
test_io_token_rate_limits.py refactor(router): count the whole router_usage family on the native store (#50862) 2026-11-13 03:22:28 +00:00
test_router.py fix(router)!: name the request size when usage-based routing refuses an over-tpm request (#51838) 2026-11-14 16:16:21 -05:00
test_router_callback_hook_sequence.py test: replace 61 live logging and otel tests with offline unit and integration coverage (#45362) 2026-10-08 15:55:57 -07:00
test_router_endpoints.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_entry_points.py feat(proxy): mixed Codex model picker and LiteLLM routing on native codex routes (#49408) 2026-11-06 11:14:47 -08:00
test_router_facade.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_fallbacks.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_fuzz_regressions_rust_only.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_get_deployments.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_helper_utils.py refactor(router): count the whole router_usage family on the native store (#50862) 2026-11-13 03:22:28 +00:00
test_router_host.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_router_max_parallel_requests.py fix(health): log Test Connection spend with the mode's call type and model id (#50987) 2026-11-11 16:07:33 -08:00
test_router_provider_endpoints.py feat(redis): serve the proxy's common Redis call with Rust stores (#50170) 2026-11-06 06:01:11 +00:00
test_router_retries.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_surface_check.py chore: move workspace packages under litellm (#51000) 2026-11-12 04:19:57 +00:00
test_router_timeout.py refactor(router): delete the python router core, the rust core is the only core (#50178) 2026-11-05 10:40:46 -08:00
test_router_vector_store_endpoints.py test: migrate SDK and proxy-booting legacy CircleCI tests to their tiers (#45758) 2026-10-11 00:17:21 -07:00