litellm - 💡(How to fix) Fix [Bug]: Non-admin team admins cannot save Key Edit Settings — UI sends `allowed_routes`, but `UpdateKeyRequest` has no `key_type` to fall back to [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#27005Fetched 2026-05-02 05:28:08
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
labeled ×2

Error Message

{"error": "Only proxy admins can set allowed_routes on a key. Use key_type to pick a preset route bucket instead."} The error message's suggested workaround ("use key_type instead") is not actionable: UpdateKeyRequest does not have a key_type field, and the UI does not send one. 2. Closest to what the error message advises — give /key/update parity with /key/generate and /key/regenerate: add key_type: Optional[LiteLLMKeyType] to UpdateKeyRequest, run handle_key_type in _validate_update_key_data, and call _check_allowed_routes_caller_permission with allow_safe_presets=True. Then update the UI to send key_type instead of allowed_routes.

Fix Action

Fix / Workaround

The error message's suggested workaround ("use key_type instead") is not actionable: UpdateKeyRequest does not have a key_type field, and the UI does not send one.

Code Example

{"error": "Only proxy admins can set `allowed_routes` on a key. Use `key_type` to pick a preset route bucket instead."}

---

case "llm_api":
  setFieldValue("allowed_routes", "llm_api_routes");
  break;
case "management":
  setFieldValue("allowed_routes", "management_routes");
  break;

---

_check_allowed_routes_caller_permission(
    allowed_routes=data.allowed_routes,
    user_api_key_dict=user_api_key_dict,
)

---
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

On v1.83.10-stable, an internal_user who is admin of a team cannot save changes to an existing team key via the UI's Edit Settings panel. The save fails with 403:

{"error": "Only proxy admins can set `allowed_routes` on a key. Use `key_type` to pick a preset route bucket instead."}

This happens even when the user did not touch the Key Type field — the form always submits the current allowed_routes value.

The error message's suggested workaround ("use key_type instead") is not actionable: UpdateKeyRequest does not have a key_type field, and the UI does not send one.

Affected versions

  • v1.83.10 (and presumably the entire v1.83.7+ line where PR #25445 first shipped)
  • Verified still broken on litellm_internal_staging tip as of commit b1fcdb671 — the strict check in _validate_update_key_data and the absence of key_type on UpdateKeyRequest are unchanged

Affected user roles

INTERNAL_USER, team admins, ORG_ADMIN — anyone whose user_role != PROXY_ADMIN. The Greptile reviewer on PR #25445 explicitly called out the org-admin case.

Why this happens — collision between two PRs

PR #16034 (UI – Add Key Type Select in Key Settings, merged Oct 30, 2025) made the Key Type dropdown a pure UI convenience that translates to allowed_routes client-side before submitting. From ui/litellm-dashboard/src/components/templates/key_edit_view.tsx:

case "llm_api":
  setFieldValue("allowed_routes", "llm_api_routes");
  break;
case "management":
  setFieldValue("allowed_routes", "management_routes");
  break;

The submit handler sends allowed_routes directly. There is no key_type field in the payload.

PR #25445 (fix(proxy): improve input validation on management endpoints, merged Apr 10, 2026) added _check_allowed_routes_caller_permission to block non-admins from setting allowed_routes on /key/generate and /key/update. The Greptile review on that PR flagged this exact problem (ORG_ADMIN role being implicitly blocked) but the PR was merged anyway.

A subsequent commit (5190bd07e, "harden raw-body acceptance", Apr 24, 2026) added an allow_safe_presets=True escape hatch — but only /key/generate (after handle_key_type resolves the preset) and /key/regenerate (with an explicit mirror re-check at line 4025) opt into it. The /key/update path in _validate_update_key_data (line 2037) still calls the strict version:

_check_allowed_routes_caller_permission(
    allowed_routes=data.allowed_routes,
    user_api_key_dict=user_api_key_dict,
)

And UpdateKeyRequest in litellm/proxy/_types.py:1065 has no key_type field, unlike GenerateKeyRequest and RegenerateKeyRequest. So even if the UI started sending key_type, the update endpoint would silently drop it.

Established precedent in this codebase

The maintainers fixed an identical class of bug on the policies field three weeks ago in commit 2c41f3c29 ("[Fix] UI - Keys: strip empty premium fields from key update payload", Apr 18, 2026). From the commit message:

The /key/update response echoes top-level defaults like policies:[] into client state. On a subsequent edit, the form resends policies:[], which the backend treats as "user is setting policies" and blocks with a 403 enterprise check regardless of value.

Drop premium metadata fields from the update payload when the current form value and the previously persisted value are both empty. Genuine clears (non-empty -> empty) still pass through so premium users can clear policies as intended.

That pattern (PREMIUM_METADATA_FIELDS in key_info_view.tsx) just hasn't been extended to allowed_routes. The same fix shape would resolve this bug.

Steps to reproduce

  1. As proxy admin, create an internal_user and assign them as admin of a team.
  2. Create a team key (any key_type, including the default).
  3. Sign in as the internal_user team admin.
  4. Open the team key → Edit Settings → click Save without changing anything.
  5. Observe 403 with the message above.

Suggested fix (any one of these works)

  1. Closest to existing pattern — extend the 2c41f3c29 UI fix to allowed_routes: in key_edit_view.tsx / key_info_view.tsx, drop allowed_routes from the update payload when the form value equals the previously persisted value. This is the smallest, lowest-risk change and matches the precedent set three weeks ago.

  2. Closest to what the error message advises — give /key/update parity with /key/generate and /key/regenerate: add key_type: Optional[LiteLLMKeyType] to UpdateKeyRequest, run handle_key_type in _validate_update_key_data, and call _check_allowed_routes_caller_permission with allow_safe_presets=True. Then update the UI to send key_type instead of allowed_routes.

  3. Backend-only — in _validate_update_key_data, skip the strict check if data.allowed_routes equals the existing key's allowed_routes. This treats "submit form unchanged" as not setting the field.

Option 1 is the lowest-risk and matches existing maintainer-authored precedent.

Related

  • PR #16034 — UI Key Type select (origin of UI sending allowed_routes on update)
  • PR #25445 — added the strict check (origin of the 403)
  • Commit 5190bd07e — added allow_safe_presets, applied to generate/regenerate but not update
  • Commit 2c41f3c29 — established UI-side precedent for this exact bug class on the policies field
  • Issue #20962 — adjacent non-admin key-creation breakage

Steps to Reproduce

  1. As proxy admin, create an internal_user and assign them as admin of a team.
  2. Create a team key (any key_type, including the default).
  3. Sign in as the internal_user team admin.
  4. Open the team key → Edit Settings → click Save without changing anything.
  5. Observe 403 with the message above.

Relevant log output

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

v1.83.10-stable

Twitter / LinkedIn details

No response

extent analysis

TL;DR

The most likely fix is to extend the existing UI fix for policies to allowed_routes by dropping allowed_routes from the update payload when the form value equals the previously persisted value.

Guidance

  • Review the code changes made in commit 2c41f3c29 to understand how the policies field was fixed and apply a similar fix to allowed_routes.
  • Consider adding a check in _validate_update_key_data to skip the strict check if data.allowed_routes equals the existing key's allowed_routes.
  • Update the UI to send key_type instead of allowed_routes and add key_type to UpdateKeyRequest for parity with /key/generate and /key/regenerate.
  • Verify the fix by testing the update functionality with an internal user as team admin.

Example

// key_edit_view.tsx / key_info_view.tsx
const updatedPayload = { ...payload };
if (updatedPayload.allowed_routes === previouslyPersistedValue.allowed_routes) {
  delete updatedPayload.allowed_routes;
}

Notes

The provided fix options have different levels of risk and complexity. Option 1, extending the existing UI fix, is the lowest-risk and most straightforward solution.

Recommendation

Apply workaround: extend the existing UI fix for policies to allowed_routes by dropping allowed_routes from the update payload when the form value equals the previously persisted value, as it is the lowest-risk and most straightforward solution.

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…

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 - 💡(How to fix) Fix [Bug]: Non-admin team admins cannot save Key Edit Settings — UI sends `allowed_routes`, but `UpdateKeyRequest` has no `key_type` to fall back to [1 participants]