litellm - ✅(Solved) Fix Admin UI router settings crashes on dict-based fallback entries that runtime supports [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#26473Fetched 2026-04-26 05:06:57
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
referenced ×3cross-referenced ×1

LiteLLM runtime supports dict-based fallback entries, but the Admin UI router settings page appears to assume fallback entries are strings only.

When router_settings.fallbacks contains an advanced fallback object like:

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "..."
          extra_headers: {}

the router works with this shape, but the Admin UI crashes when viewing router settings.

Browser console error:

Uncaught Error: Minified React error #31; visit https://react.dev/errors/31?args[]=object%20with%20keys%20%7Bmodel%2C%20api_key%2C%20extra_headers%7D

This looks like the UI is trying to render the fallback object directly as a React child.

Error Message

Root Cause

This fallback shape is useful for real cases where fallback must override request-level auth.

Example:

  • primary model uses auth injected by a proxy/custom hook
  • request fails and falls back to another model/provider
  • fallback must explicitly replace stale api_key / Authorization state

Without dict-based fallback entries, standard string fallback can reuse the wrong auth across fallback attempts.

Fix Action

Fixed

PR fix notes

PR #26515: fix(ui): render dict-shaped fallback entries in router settings

Description (problem / solution / changelog)

Relevant issues

Fixes #26473

Pre-Submission checklist

  • Tests added — 5 new regression cases in ui/litellm-dashboard/src/components/Settings/RouterSettings/Fallbacks/Fallbacks.test.tsx. UI-only change, so tests/test_litellm/ does not apply here.
  • UI build passes (npm run build ✅), vitest passes (47/47 in RouterSettings/**, 20/20 in Fallbacks.test.tsx).
  • make test-unit not impacted — no Python files touched.
  • Scope isolated — only fixes the router-settings dict-fallback render crash.
  • Greptile review — will request @greptileai after the PR is open.

Type

🐛 Bug Fix

Changes

Problem

router_settings.fallbacks accepts dict-shaped chain entries at runtime, e.g.

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "..."
          extra_headers: {}

This shape is used to override request-level params (notably api_key / Authorization) on the fallback attempt — important when the primary model uses request-injected auth that must not carry over to the fallback. Runtime support lives in litellm/router_utils/fallback_event_handlers.py:122-132 (kwargs.update(mg) for dict items) and _check_non_standard_fallback_format.

The Admin UI's Fallbacks.tsx typed each chain entry as string and rendered it directly as a React child, so any dict entry crashed the router-settings page:

Uncaught Error: Objects are not valid as a React child (found: object with keys {model, api_key, extra_headers}).

(React error #31 — exactly what the issue reports.)

Fix (UI-only)

ui/litellm-dashboard/src/components/Settings/RouterSettings/Fallbacks/Fallbacks.tsx:

  • Widened the chain-item type to FallbackChainItem = string | { model?: string; [key: string]: any }.
  • Added getFallbackChainItemDisplayName() to resolve the visible label from string, dict.model, or stringified JSON.
  • ChainCard now tags dict entries with an override badge and shows the override JSON in a tooltip on hover.
  • api_key, authorization, token, secret, password (and matching keys inside extra_headers) are masked with •••••• so secrets never enter the DOM.
  • React keys made index-stable (\${i}-\${displayName}) since the same model can repeat across overrides.

The existing add/delete flows already preserved unrelated entries unchanged, so dict items round-trip safely with no backend changes. UpdateRouterConfig.fallbacks: Optional[List[dict]] already permits the dict shape on /config/update.

Tests

ui/litellm-dashboard/src/components/Settings/RouterSettings/Fallbacks/Fallbacks.test.tsx adds 5 cases under dict-shaped fallback chain entries:

  1. renders without crashing when a fallback chain entry is a dict — locks in the React error #31 fix.
  2. marks dict fallback entries with an override tag — visual signal that the entry has overrides.
  3. renders mixed string and dict entries in the same chain — exactly one override tag for the dict, none for the string.
  4. preserves dict fallbacks when deleting a sibling fallback row — round-trip safety: the dict entry is unchanged after a setCallbacksCall triggered by deleting another row.
  5. does not leak api_key into the rendered DOM — masking guarantee.

Suite results:

  • Fallbacks.test.tsx: 20/20 ✅ (15 pre-existing + 5 new)
  • RouterSettings/**: 47/47
  • npm run build: ✅
  • tsc --noEmit (filtered to touched files): clean ✅

Repro confirmation

I temporarily reverted the patch and ran the new dict-fallback test. It produced the exact error from the issue:

Error: Objects are not valid as a React child (found: object with keys {model, api_key, extra_headers}).

With the patch applied the same render shows the model name, an override tag, and a masked-JSON tooltip — no crash.

Screenshots / Proof of Fix

(Vitest output rather than screenshots, since the proof is a render-crash assertion):

✓ src/.../Fallbacks.test.tsx (20 tests) 663ms
  ✓ Fallbacks > dict-shaped fallback chain entries > renders without crashing when a fallback chain entry is a dict
  ✓ Fallbacks > dict-shaped fallback chain entries > marks dict fallback entries with an override tag
  ✓ Fallbacks > dict-shaped fallback chain entries > renders mixed string and dict entries in the same chain
  ✓ Fallbacks > dict-shaped fallback chain entries > preserves dict fallbacks when deleting a sibling fallback row
  ✓ Fallbacks > dict-shaped fallback chain entries > does not leak api_key into the rendered DOM

Test Files  1 passed (1)
     Tests  20 passed (20)

Changed files

  • litellm/litellm_core_utils/prompt_templates/factory.py (modified, +3/-1)
  • litellm/llms/predibase/chat/transformation.py (modified, +10/-3)
  • litellm/proxy/guardrails/guardrail_hooks/xecguard/xecguard.py (modified, +6/-3)
  • ui/litellm-dashboard/src/components/Settings/RouterSettings/Fallbacks/Fallbacks.test.tsx (modified, +164/-14)
  • ui/litellm-dashboard/src/components/Settings/RouterSettings/Fallbacks/Fallbacks.tsx (modified, +80/-39)

Code Example

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "..."
          extra_headers: {}

---

Uncaught Error: Minified React error #31; visit https://react.dev/errors/31?args[]=object%20with%20keys%20%7Bmodel%2C%20api_key%2C%20extra_headers%7D

---

model_list:
  - model_name: primary-model
    litellm_params:
      model: provider_a/primary-deployment
      api_base: https://provider-a.example.com/v1
      api_version: "YYYY-MM-DD"

  - model_name: fallback-model
    litellm_params:
      model: provider_b/fallback-deployment
      api_base: https://provider-b.example.com/v1
      api_key: "fallback-key"

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "fallback-key"
          extra_headers: {}
RAW_BUFFERClick to expand / collapse

Summary

LiteLLM runtime supports dict-based fallback entries, but the Admin UI router settings page appears to assume fallback entries are strings only.

When router_settings.fallbacks contains an advanced fallback object like:

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "..."
          extra_headers: {}

the router works with this shape, but the Admin UI crashes when viewing router settings.

Browser console error:

Uncaught Error: Minified React error #31; visit https://react.dev/errors/31?args[]=object%20with%20keys%20%7Bmodel%2C%20api_key%2C%20extra_headers%7D

This looks like the UI is trying to render the fallback object directly as a React child.

Why this matters

This fallback shape is useful for real cases where fallback must override request-level auth.

Example:

  • primary model uses auth injected by a proxy/custom hook
  • request fails and falls back to another model/provider
  • fallback must explicitly replace stale api_key / Authorization state

Without dict-based fallback entries, standard string fallback can reuse the wrong auth across fallback attempts.

Repro

  1. Start LiteLLM proxy with a config containing:
model_list:
  - model_name: primary-model
    litellm_params:
      model: provider_a/primary-deployment
      api_base: https://provider-a.example.com/v1
      api_version: "YYYY-MM-DD"

  - model_name: fallback-model
    litellm_params:
      model: provider_b/fallback-deployment
      api_base: https://provider-b.example.com/v1
      api_key: "fallback-key"

router_settings:
  fallbacks:
    - primary-model:
        - model: fallback-model
          api_key: "fallback-key"
          extra_headers: {}
  1. Open LiteLLM Admin UI.
  2. Go to Router Settings / Fallbacks.
  3. Observe browser console and page rendering.

Actual behavior

  • Admin UI crashes or fails to render the fallback section.
  • Browser console shows React error #31 with the fallback object keys: {model, api_key, extra_headers}

Expected behavior

One of these should happen:

  1. The Admin UI supports rendering/editing dict-based fallback entries.
  2. The Admin UI gracefully displays them as JSON/read-only values.
  3. The backend/UI validation clearly rejects unsupported fallback shapes instead of crashing.

Notes

The runtime appears to support this shape already:

  • litellm/router_utils/fallback_event_handlers.py checks for non-standard fallback format where list items are dicts with LiteLLM param keys.

The Admin fallback management types appear string-only:

  • litellm/types/management_endpoints/router_settings_endpoints.py fallback_models: List[str]

So this seems to be a runtime/UI contract mismatch.

Version / Environment

  • LiteLLM installed from current package / proxy UI bundle
  • Observed on April 24, 2026
  • Local runtime also shows support for dict fallback entries in Python router code

Suggested fix

  • Update Admin UI fallback rendering to handle string | object fallback entries
  • Or explicitly normalize dict entries to a display-safe string / JSON block
  • Or validate and reject unsupported shapes before the UI tries to render them

extent analysis

TL;DR

Update the Admin UI to handle dict-based fallback entries by rendering them as JSON or validating and rejecting unsupported shapes.

Guidance

  • Review the litellm/types/management_endpoints/router_settings_endpoints.py file to update the fallback_models type to support both strings and objects.
  • Modify the Admin UI code to handle the new type by either rendering dict-based fallback entries as JSON or displaying them as read-only values.
  • Consider adding validation to reject unsupported fallback shapes before rendering to prevent UI crashes.
  • Check the litellm/router_utils/fallback_event_handlers.py file to ensure it correctly handles the updated fallback format.

Example

# Example of updating the fallback_models type
from typing import Union

fallback_models: Union[str, dict]

Notes

The provided solution assumes that the issue is solely related to the UI rendering and not a deeper problem with the runtime or backend logic. Further investigation may be necessary to ensure the updated UI correctly interacts with the backend.

Recommendation

Apply a workaround by updating the Admin UI to handle dict-based fallback entries, as this seems to be the most straightforward solution to the described problem. This approach allows for a more robust and user-friendly experience while maintaining the existing runtime functionality.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

One of these should happen:

  1. The Admin UI supports rendering/editing dict-based fallback entries.
  2. The Admin UI gracefully displays them as JSON/read-only values.
  3. The backend/UI validation clearly rejects unsupported fallback shapes instead of crashing.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - ✅(Solved) Fix Admin UI router settings crashes on dict-based fallback entries that runtime supports [1 pull requests, 1 participants]