Commit graph

36182 commits

Author SHA1 Message Date
Sameer Kankute
839f3e32d4
fix(docs+tests): fix health_check_ignore_transient_errors doc section and test coverage
- Move health_check_ignore_transient_errors from router_settings to
  general_settings in config_settings.md (code reads it from general_settings)
- Remove duplicate enable_health_check_routing / health_check_staleness_threshold
  entries that were incorrectly listed under router_settings
- Replace TestHealthCheckEndpointExceptionPropagation tests with ones that
  exercise the real _perform_health_check code path via mocked ahealth_check,
  verifying exceptions appear in exceptions_by_model_id and NOT in endpoint dicts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:03:06 +05:30
Sameer Kankute
d0b04a7d52
revert: undo allowed_fails_policy gate on cooldown loop
Cooldown integration via health checks is intentional for all
enable_health_check_routing users, not just those with allowed_fails_policy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:11 +05:30
Sameer Kankute
aa17af2a37
fix(health-check-routing): gate cooldown loop behind allowed_fails_policy
Without the policy, cooldown is not the routing exclusion mechanism.
Firing _set_cooldown_deployments for all enable_health_check_routing users
was a backwards-incompatible change — 401s would immediately cooldown
deployments that the binary filter would have recovered on the next cycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:11 +05:30
Sameer Kankute
92df1e77fa
fix(health-check-routing): fix P1 transient-error filter broken on cache hits
When SharedHealthCheckManager returns cached results, exceptions_by_model_id
is always {} so the transient-error filter defaulted to status 500 for all
endpoints, incorrectly marking 429/408 endpoints as unhealthy.

Fix: store integer exception_status on each unhealthy endpoint dict in
_perform_health_check. _get_endpoint_exception_status() uses the live
exception object when available (direct path) and falls back to the stored
integer (cache-hit path). The integer is JSON-serializable and survives
the shared cache round-trip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:11 +05:30
Sameer Kankute
34ce4da8cb
fix(health-check-routing): fix P0 cooldown integration never firing
The cooldown loop was reading endpoint.get("exception") which is always
None because exceptions are now returned via exceptions_by_model_id, not
stored in endpoint dicts. Fixed to use _exceptions.get(model_id).

Also fixes the transient-error filter to use _exceptions instead of
endpoint.get("exception"), and fixes all remaining 2-value return sites
in shared_health_check_manager.py. Tests updated to pass exceptions via
exceptions_by_model_id parameter instead of endpoint dicts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:11 +05:30
Sameer Kankute
6dfde8ce2b
fix(shared-health-check): fix remaining 2-value return sites and update type annotation 2026-04-02 22:00:10 +05:30
Sameer Kankute
a756424192
fix(health-check-routing): properly isolate exceptions from health response
Return exceptions_by_model_id as a separate third value from
_perform_health_check / perform_health_check so exception objects
(which contain non-JSON-serializable httpx URL types) never appear
in the endpoint dicts that get serialized by the /health response.

Callers updated: _health_endpoints.py, shared_health_check_manager.py,
proxy_server.py background loop. All use the exceptions dict only for
cooldown integration, not for display.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:10 +05:30
Sameer Kankute
5850b1130e
fix(router): address greptile review comments
- Narrow cooldown safety-net bypass: only fires when allowed_fails_policy
  is set (cooldown is health-check driven). Without a policy, cooldowns
  are from real request failures and must not be bypassed.
- Restore cooldown deployments DEBUG log that was accidentally removed.
- Fix test_health TypeError: move exception extraction to a separate
  exceptions_by_model_id dict returned alongside endpoints, so exception
  objects never appear in the endpoint dicts that get JSON-serialized
  by the /health response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:00:10 +05:30
Sameer Kankute
fc155c7bfa
Fix litellm/tests/proxy_unit_tests/test_proxy_server.py 2026-04-02 22:00:10 +05:30
Sameer Kankute
8bf927e3a3
fix(health-check-routing): fix three CI failures
- Add "exception" to ILLEGAL_DISPLAY_PARAMS in health_check.py so the
  exception object is stripped before the health endpoint serializes
  results to JSON (fixes TypeError: 'URL' object is not iterable)
- Add allowed_fails_policy = None to FakeRouter stubs in
  test_router_health_check_routing.py (fixes AttributeError)
- Add health_check_ignore_transient_errors to config_settings.md router
  settings reference table (fixes documentation test)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:59:56 +05:30
Sameer Kankute
db73b35280
docs(router): add health check driven routing guide
New standalone page covering the full health check routing feature:
allowed_fails_policy integration, health_check_ignore_transient_errors,
architecture SVG, step-by-step setup, and gotchas (TTL, AllowedFails semantics).

Replaces the inline section in health.md with a link to the new page.
Added to the Routing & Load Balancing sidebar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:58:58 +05:30
Sameer Kankute
553a7229c1
fix(router): also exclude 429/408 from health state cache when ignore_transient_errors set
The previous fix only skipped cooldown counter increments. The health state
cache was still marking 429/408 endpoints as is_healthy=False, causing the
binary health check filter to exclude them from routing.

Now, when health_check_ignore_transient_errors=True, 429/408 endpoints are
also excluded from the unhealthy list passed to build_deployment_health_states(),
so the binary filter treats them as unaffected (not unhealthy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:58:58 +05:30
Sameer Kankute
b8391bc17c
feat(router): add health_check_ignore_transient_errors flag
When enabled, health check failures with 429 (rate limit) or 408 (timeout)
status codes are skipped from the cooldown pipeline. These are transient
load issues, not broken deployments. Auth errors (401), 404, and 5xx errors
still increment counters and trigger cooldown as before.

Config (general_settings):
  health_check_ignore_transient_errors: true

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:58:57 +05:30
Sameer Kankute
1867ca51ae
feat(router): integrate allowed_fails_policy into health check failures
Health check failures now increment the same per-deployment failure
counters used by allowed_fails_policy, so users can control how many
health check failures of each error type are required before a
deployment enters cooldown.

- ahealth_check() preserves the original exception in its return dict
- run_with_timeout() returns a litellm.Timeout on health check timeout
- _perform_health_check() propagates exceptions to unhealthy endpoints
- _write_health_state_to_router_cache() calls _set_cooldown_deployments
  for each unhealthy endpoint that has an exception
- When allowed_fails_policy is set, the binary health check filter is
  bypassed so cooldown is the sole routing exclusion mechanism
- Safety net: if all deployments are in cooldown with
  enable_health_check_routing=True, the cooldown filter is bypassed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:58:53 +05:30
Sameer Kankute
7f1b34cb1a
fix(docker): include enterprise bridge in non-root runtime image
Copy the /app/enterprise bridge package into the non-root runtime image so enterprise proxy hooks register correctly (including managed_files).
2026-04-02 21:55:15 +05:30
Sameer Kankute
6af9ce7fd4
fix: revert accidental _litellm_uuid import back to _uuid
The isort hook picked up a stale rename from the working directory.
Both router.py and proxy_server.py need litellm._uuid, not _litellm_uuid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:55:00 +05:30
Sameer Kankute
80238ba908
fix: re-attach model_id after endpoint cleaning, bump log level
- model_id is now added after _clean_endpoint_data() so it survives
  health_check_details: False (MINIMAL_DISPLAY_PARAMS filtering)
- Health state write failures logged at warning instead of debug

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:55:00 +05:30
Sameer Kankute
44a3a833c6
feat(router): add health-check-driven routing behind opt-in flag
Background health checks now feed deployment health state into the
router candidate-filtering pipeline. Unhealthy deployments are excluded
proactively instead of waiting for request failures to trigger cooldown.

Gated by `enable_health_check_routing: true` in general_settings.
Off by default — zero behavior change for existing users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:55:00 +05:30
Sameer Kankute
158732db59
docs: remove enable_pre_call_checks requirement from order docs
Order-based routing and fallback work without enable_pre_call_checks
in the current code. Remove the stale requirement from both doc files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:54:31 +05:30
Sameer Kankute
2950677e5d
fix(router): handle non-standard fallback formats with order-based fallback
When fallbacks use non-standard formats (e.g. ["claude-3-haiku"] or
[{"model": "...", "messages": [...]}]), detect them with
_check_non_standard_fallback_format and pass them through directly
instead of trying to parse with get_fallback_model_group which only
handles the standard dict-keyed format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:54:30 +05:30
Sameer Kankute
6295e6b3d8
feat(router): add order-based fallback so higher order deployments are tried on failure
When a request to an order=1 deployment fails, the router now
automatically tries order=2, order=3, etc. before falling through to
external fallbacks. Works for all error types (429, 404, connection
errors). Requires enable_pre_call_checks=True.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:54:30 +05:30
Sameer Kankute
cd0a141115
fix(router): address Greptile P0/P1 review comments on order fallback
- P0: Skip order-based fallback for ContextWindowExceededError and
  ContentPolicyViolationError so their dedicated fallback handlers run
- P1: Read _target_order from kwargs to skip already-tried order levels,
  preventing wasteful retries and exponential retry storms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:54:30 +05:30
Sameer Kankute
9cbe3c2c7f
feat(router): add order-based fallback so higher order deployments are tried on failure
When order=1 deployments fail, the router now automatically tries order=2,
then order=3, etc. before falling through to external fallbacks. This removes
the need for enable_pre_call_checks and makes order work as a true priority-based
fallback chain within a model group.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 21:54:30 +05:30
Harshit28j
ba65efe32e
fix: address Greptile review feedback on key rotation lock 2026-04-02 21:53:03 +05:30
Krrish Dholakia
40879e7066 fix: remove dead migration sql 2026-03-23 20:14:37 -07:00
Ishaan Jaffer
659d4013c5 fix: address Greptile review issues
- GCPIAMCredentialProvider now inherits from redis.credentials.CredentialProvider
  so redis-py's async path calls get_credentials_async() properly
- move _redis_credential_provider import to top of _redis.py (PEP 8)
- remove dead else-branch that silently no-oped (gcp_service_account from
  redis_kwargs.get() was always None since it's popped by _get_redis_client_logic)
- remove mid-function 'from litellm import get_secret_str' inline import
- remove unused 'call' import from test_redis.py
2026-03-23 10:17:43 -07:00
Ishaan Jaffer
a1494b59a3 refactor(redis): move GCPIAMCredentialProvider to its own file
Extract GCPIAMCredentialProvider and _generate_gcp_iam_access_token
into litellm/_redis_credential_provider.py. _redis.py imports them
from there, keeping the public API unchanged.
2026-03-23 10:17:43 -07:00
Ishaan Jaffer
67b752ca8f fix(redis): regenerate GCP IAM token per connection for async cluster clients
Async RedisCluster was generating the IAM token once at startup and
storing it as a static password. After the 1-hour GCP token TTL, any
new connection (including to newly-discovered cluster nodes) would fail
to authenticate.

Fix: introduce GCPIAMCredentialProvider that implements redis-py's
CredentialProvider protocol. It calls _generate_gcp_iam_access_token()
on every new connection, matching what the sync redis_connect_func
already does. async_redis.RedisCluster accepts a credential_provider
kwarg which is invoked per-connection.
2026-03-23 10:17:43 -07:00
yuneng-jiang
9e98a7d7b3 Merge branch 'main' of github.com:BerriAI/litellm into litellm_rc_branch 2026-03-21 23:50:45 -07:00
yuneng-jiang
c89496f378
Merge pull request #24342 from BerriAI/litellm_yj_march_21_2026
[Fix] UI - Teams: Table refresh, infinite dropdown, leftnav migration
2026-03-21 23:36:21 -07:00
yuneng-jiang
38d477507d remove outdated e2e test 2026-03-21 23:14:53 -07:00
yuneng-jiang
6bb08883af adding poetry lock 2026-03-21 23:01:28 -07:00
yuneng-jiang
fa65433c8c bump: version 1.82.5 → 1.82.6 2026-03-21 22:56:09 -07:00
yuneng-jiang
d91980dc45 adding build 2026-03-21 22:55:04 -07:00
yuneng-jiang
071c8641de bump: version 0.4.59 → 0.4.60 2026-03-21 22:54:41 -07:00
yuneng-jiang
88a4c7aeaf bump: version 0.4.58 → 0.4.59 2026-03-21 22:54:38 -07:00
yuneng-jiang
34d079910b chore: update Next.js build artifacts (2026-03-22 05:53 UTC, node v22.16.0) 2026-03-21 22:53:50 -07:00
yuneng-jiang
9073daeebc [Fix] UI - TeamDropdown: Match org dropdown styling and fix test mock
- Use Select.Option with font-medium alias + Text secondary ID to match OrganizationDropdown
- Default page size to 20
- Add useInfiniteTeams mock to AddModelForm tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:52:16 -07:00
yuneng-jiang
aea8e32048 [Fix] UI: Team table refresh, infinite team dropdown, leftnav for dashboard routes
- OldTeams: refresh table via fetchTeamsV2 after team create instead of appending
- TeamDropdown: rewrite with useInfiniteTeams for paginated fetch, scroll-to-load, and debounced search
- Update all TeamDropdown consumers to use the new self-fetching API
- Dashboard layout: switch from Sidebar2 to SidebarProvider (leftnav)
- Leftnav: add MIGRATED_PAGES routing for path-based navigation (api-reference)
- Navbar: remove chat button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:05:26 -07:00
yuneng-jiang
9963b31e07 Revert "fix(proxy): restore per-entity breakdown in aggregated daily activity endpoint"
This reverts commit 9c3fab24ad.
2026-03-21 21:37:29 -07:00
yuneng-jiang
f5194b5ce3
Merge pull request #24334 from BerriAI/litellm_yj_march_21_2026
[Infra] Build UI for release
2026-03-21 18:03:38 -07:00
yuneng-jiang
d217e49193 chore: update Next.js build artifacts (2026-03-22 01:02 UTC, node v22.16.0) 2026-03-21 18:02:32 -07:00
yuneng-jiang
e3d4c29d37
Merge pull request #24323 from BerriAI/litellm_ryan_march_20
litellm ryan march 20
2026-03-21 15:57:28 -07:00
Ryan Crabbe
3e27ff1b78 fix: resolve mypy type errors in audit_logs.py 2026-03-21 15:42:01 -07:00
Ryan Crabbe
f494ab513f docs: add High Availability Control Plane documentation
New docs page covering the HA control plane architecture where each
worker instance has its own DB, Redis, and master key. Includes a
React component diagram, setup configs, SSO notes, and local testing
instructions.
2026-03-21 15:31:49 -07:00
yuneng-jiang
1986f1034e
Merge pull request #24211 from BerriAI/litellm_dev_sameer_16_march_week
Litellm dev sameer 16 march week
2026-03-21 15:19:15 -07:00
yuneng-jiang
72fba093c8 Merge remote-tracking branch 'origin/main' into litellm_dev_sameer_16_march_week 2026-03-21 15:11:29 -07:00
yuneng-jiang
7b31ea40a9
Merge pull request #22844 from BerriAI/litellm_oss_staging_03_05_2026
Litellm oss staging 03 05 2026
2026-03-21 15:09:48 -07:00
Ryan Crabbe
9b90e80f71 fix: resolve mypy type errors in audit_logs.py
Extract multiline `or` chain from LiteLLM_AuditLogs constructor to fix
pydantic mypy plugin field-type misattribution, and add explicit
Optional[bool] annotation to avoid variable name shadowing conflict.
2026-03-21 15:08:47 -07:00
yuneng-jiang
c6bb7a5be5 Apply Black formatting to 11 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:05:53 -07:00