Generic Guardrails: Add a configurable fallback to handle generic guardrail endpoint connection failures#21245
Conversation
…ndpoint connection failures
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@ greptileai |
Greptile SummaryThis PR adds a configurable
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py | Core implementation of fail-open/fail-closed fallback for httpx.RequestError. Logic is sound for connection-level errors but does not cover HTTP 502/503 errors that could indicate an unreachable endpoint behind a reverse proxy. |
| litellm/types/guardrails.py | Adds unreachable_fallback to BaseLitellmParams, which is the base for ALL guardrail types — not just Generic Guardrail API. The field is exposed in configs for all guardrails but only consumed by generic_guardrail_api, which may confuse users of other guardrail types. |
| litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py | Adds unreachable_fallback to GenericGuardrailAPIOptionalParams with proper type and documentation. Minor formatting change to litellm_trace_id. |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/init.py | Passes unreachable_fallback from config to GenericGuardrailAPI constructor with a safe default of fail_closed. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py | Adds two well-structured unit tests covering both fail_closed (default) and fail_open behavior. All tests use mocks — no real network calls. |
| docs/my-website/docs/adding_provider/generic_guardrail_api.md | Documents the new unreachable_fallback config option with clear description of both modes. |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/example_config.yaml | Adds unreachable_fallback example with both options documented in a comment. |
Flowchart
flowchart TD
A[apply_guardrail called] --> B[Build request payload]
B --> C[POST to guardrail endpoint]
C --> D{Response received?}
D -->|Yes| E[raise_for_status]
E -->|2xx| F{action == BLOCKED?}
F -->|Yes| G[Raise GuardrailRaisedException]
F -->|No| H[Return inputs with modifications]
E -->|4xx/5xx| I[HTTPStatusError caught by generic except]
I --> J[Raise Exception - always]
D -->|No - RequestError| K{unreachable_fallback?}
K -->|fail_closed| L[Log error + Raise Exception]
K -->|fail_open| M[Log CRITICAL + Return inputs unchanged]
Last reviewed commit: 653293c
litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
Show resolved
Hide resolved
litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
Outdated
Show resolved
Hide resolved
Greptile SummaryThis PR adds a configurable
Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py | Core implementation of fail_open/fail_closed logic. Well-structured with extracted helpers. Has a bug where timeout errors bypass the fail_open path because AsyncHTTPHandler.post() converts httpx.TimeoutException to litellm.Timeout (not httpx.RequestError). |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/init.py | Passes the new unreachable_fallback param through to GenericGuardrailAPI constructor. Clean and consistent with existing parameter forwarding pattern. |
| litellm/types/guardrails.py | Adds unreachable_fallback field to BaseLitellmParams with clear documentation noting it's only implemented for generic_guardrail_api. Also adds it to the normalize_lowercase validator. |
| litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py | Adds unreachable_fallback to GenericGuardrailAPIOptionalParams for UI/config model. Minor formatting changes to litellm_trace_id. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py | Adds 3 new tests for fail_open/fail_closed behavior. All mock-based (no real network calls). Missing test for timeout scenario, which is the gap in the implementation. |
| docs/my-website/docs/adding_provider/generic_guardrail_api.md | Adds documentation for the new unreachable_fallback config option with clear description of behavior. |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/example_config.yaml | Adds unreachable_fallback example to the config YAML template with inline comment describing options. |
Flowchart
flowchart TD
A[apply_guardrail called] --> B[Build request payload]
B --> C[async_handler.post to guardrail endpoint]
C -->|Success 2xx| D[Parse response]
D -->|action=BLOCKED| E[Raise GuardrailRaisedException]
D -->|action=NONE/INTERVENED| F[Return inputs with modifications]
C -->|httpx.HTTPStatusError| G{Status code 502/503/504?}
G -->|Yes| H{unreachable_fallback?}
G -->|No| I[Raise Exception]
H -->|fail_open| J[Log CRITICAL & proceed]
H -->|fail_closed| I
C -->|httpx.RequestError| K{unreachable_fallback?}
K -->|fail_open| J
K -->|fail_closed| I
C -->|litellm.Timeout| L["Falls to generic except Exception ⚠️"]
L --> I
style L fill:#ff6b6b,stroke:#c92a2a,color:#fff
style J fill:#51cf66,stroke:#2b8a3e,color:#fff
Last reviewed commit: 207b622
litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py
Show resolved
Hide resolved
Greptile SummaryThis PR adds a configurable
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py | Core implementation of fail-open/fail-closed fallback behavior. Adds exception handlers for litellm.Timeout, httpx.HTTPStatusError (502/503/504), and httpx.RequestError. Refactors return-value construction into helper methods. The response.raise_for_status() on line 408 is dead code (already called by AsyncHTTPHandler.post), but pre-existing. |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/init.py | Passes unreachable_fallback from parsed config to GenericGuardrailAPI constructor via getattr with default. |
| litellm/types/guardrails.py | Adds unreachable_fallback field to BaseLitellmParams (shared base for all guardrails) with clear documentation that it only applies to generic_guardrail_api. Also adds it to the normalize_lowercase field validator list. |
| litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py | Adds unreachable_fallback field to GenericGuardrailAPIOptionalParams for UI/config model. Minor reformatting of litellm_trace_id field. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/test_generic_guardrail_api.py | Adds 4 new tests covering: default fail_closed behavior, fail_open with network errors, fail_open with HTTP 503, and fail_open with litellm.Timeout. All tests use mocks (no real network calls) and cover the key scenarios well. |
| docs/my-website/docs/adding_provider/generic_guardrail_api.md | Adds unreachable_fallback config option to the documentation example with clear description. |
| litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/example_config.yaml | Adds unreachable_fallback option to the example config YAML file. |
Flowchart
flowchart TD
A[apply_guardrail called] --> B[POST to guardrail endpoint]
B --> C{Response OK?}
C -->|Yes| D{action == BLOCKED?}
D -->|Yes| E[Raise GuardrailRaisedException]
D -->|No| F[Return inputs with response modifications]
C -->|No - Exception| G{Exception Type?}
G -->|GuardrailRaisedException| E
G -->|litellm.Timeout| H{unreachable_fallback?}
G -->|httpx.HTTPStatusError 502/503/504| H
G -->|httpx.RequestError| H
G -->|httpx.HTTPStatusError other| I[Raise Exception]
G -->|Other Exception| I
H -->|fail_open| J[Log CRITICAL + return original inputs]
H -->|fail_closed| I
Last reviewed commit: ffb5aa1
Additional Comments (1)
This is pre-existing (not introduced by this PR), but worth noting since this method is being refactored anyway. |
bc2fefd
into
BerriAI:litellm_oss_staging_02_16_2026
Add a configurable fallback to handle generic guardrail endpoint connection failures
Relevant issues
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🆕 New Feature
📖 Documentation
✅ Test
Changes
unreachable_fallbackconfig option forgeneric_guardrail_api(fail_closed default, fail_open on network/unreachable errors).When

fail_closed(same like before):When

fail_open(log critical, but continue the flow):