Skip to content

fix(proxy): return 503 from CLI SSO endpoints when the configured Redis is unreachable - #34878

Open
ryan-crabbe-berri wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_cli_sso_redis_503
Open

fix(proxy): return 503 from CLI SSO endpoints when the configured Redis is unreachable#34878
ryan-crabbe-berri wants to merge 1 commit into
litellm_internal_stagingfrom
litellm_cli_sso_redis_503

Conversation

@ryan-crabbe-berri

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • /sso/cli/start returns a raw 500 when the configured Redis is down
  • a failed login-session write is swallowed, surfacing later as a confusing 400

How it solves it:

  • both paths now fail closed with a deliberate 503
  • the 503 tells the operator the configured Redis is unreachable

Relevant issues

Linear ticket

Pre-Submission checklist

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

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • 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

Setup: throwaway Redis on :6390 (docker run -d --rm --name qa-redis-cli-sso -p 6390:6379 redis:7-alpine), local proxy on :4155 with the coordination Redis pointed at it:

general_settings:
  master_key: sk-1234
  coordination_redis:
    host: localhost
    port: 6390

Healthy Redis, fix applied (commit 8fc7946); CLI login start works as before:

$ curl -s -w '\nHTTP %{http_code}\n' -X POST http://localhost:4155/sso/cli/start
{"login_id":"cli-KKgss5UlFYh8bGa_IVJotcTy3Mh8GSRA","poll_secret":"khDMFNOTAjp2LTPtBUtZw1kJ7BhR-t6xNGFkEgSqjxE","user_code":"3BVS-E857","expires_in":600}
HTTP 200

Before the fix (same setup, ui_sso.py and redis_cache.py at litellm_internal_staging daf22ec), with Redis stopped (docker stop qa-redis-cli-sso):

$ curl -s -w '\nHTTP %{http_code}\n' -X POST http://localhost:4155/sso/cli/start
{"error":{"message":"Internal server error","type":"internal_server_error"}}
HTTP 500

with the proxy log showing the unhandled error:

  File ".../litellm/caching/redis_cache.py", line 421, in increment_cache
    result: int = _redis_client.incr(name=key, amount=value)
redis.exceptions.ConnectionError: Error 61 connecting to localhost:6390. Connection refused.

After the fix (commit 8fc7946), same stopped Redis:

$ curl -s -w '\nHTTP %{http_code}\n' -X POST http://localhost:4155/sso/cli/start
{"detail":"CLI login requires the proxy's configured Redis cache, which is currently unreachable. Retry once Redis is healthy."}
HTTP 503

Type

🐛 Bug Fix

Changes

litellm-proxy login runs a device-code flow whose session blob is deliberately Redis-authoritative when a coordination Redis is configured (PR #33261), so the browser callback and the CLI poll can land on different pods. When that Redis is unreachable, two things went wrong in /sso/cli/start. The per-IP rate-limit increment goes through DualCache.increment_cache, the one sync cache path that re-raises, so the raw redis.exceptions.ConnectionError escaped as a 500. The login-session write had the opposite problem: sync RedisCache.set_cache swallows errors, so the session was silently stored nowhere and the failure resurfaced later as a misleading 400 "session not found" at poll time

Both paths in ui_sso.py now fail closed with a single deliberate 503 telling the operator the configured Redis cache is unreachable. Failing closed keeps the login rate limiter intact instead of failing open exactly when the shared counter is gone. There is intentionally no in-memory fallback: it could only help a single-pod deployment whose Redis is down, and in multi-pod it would replace one clear error with intermittent hard-to-debug 400s

To make the write loud without changing any existing caller, RedisCache.set_cache gains an opt-in raise_on_error flag (default False, so the fire-and-forget contract everywhere else is unchanged)

Deployments without any Redis configured are unaffected and keep the in-memory single-pod behavior

Tests: regression tests assert /sso/cli/start returns 503 (not 500) when the increment raises, that a failed Redis session write raises 503 instead of silently no-op'ing, and that set_cache still swallows by default while raising on opt-in

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

…is is unreachable

/sso/cli/start propagated a raw redis ConnectionError as a 500 because the
per-IP rate-limit increment is the one cache path that re-raises. The
Redis-authoritative flow write had the opposite problem: it silently
swallowed the failure, stored the login session nowhere, and deferred the
error to a confusing 400 at poll time.

Both now fail closed with a deliberate 503 telling the operator the
configured Redis cache is unreachable. RedisCache.set_cache gains an
opt-in raise_on_error flag (default False, existing callers unchanged) so
callers whose data lives only in Redis can hear about failed writes.
@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes CLI SSO fail closed when its configured Redis backend is unavailable.

  • Adds opt-in error propagation to synchronous Redis cache writes while preserving the default fire-and-forget behavior.
  • Converts CLI SSO rate-limit and session-write failures into explicit HTTP 503 responses.
  • Adds regression coverage for unavailable Redis and both Redis write-error modes.

Confidence Score: 5/5

The PR appears safe to merge with no actionable defects identified.

The changed paths preserve existing cache-write behavior by default while making Redis-authoritative CLI SSO operations fail explicitly before issuing an unusable login session.

Important Files Changed

Filename Overview
litellm/caching/redis_cache.py Adds backward-compatible opt-in propagation of synchronous Redis write errors.
litellm/proxy/management_endpoints/ui_sso.py Maps CLI SSO rate-limit and authoritative session-write failures to deliberate 503 responses without introducing a fallback.
tests/test_litellm/caching/test_redis_cache.py Verifies that Redis writes still swallow errors by default and propagate them when explicitly requested.
tests/test_litellm/proxy/management_endpoints/test_ui_sso.py Adds regression coverage for unavailable Redis during CLI SSO rate limiting and session persistence.

Reviews (1): Last reviewed commit: "fix(proxy): return 503 from CLI SSO endp..." | Re-trigger Greptile

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_cli_sso_redis_503 (8fc7946) with litellm_internal_staging (daf22ec)

Open in CodSpeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant