Skip to content

fix(proxy): restore management_v1 query-param validation under fastapi>=0.140.7 - #35773

Merged
yuneng-berri merged 2 commits into
BerriAI:litellm_internal_stagingfrom
HuanQian571:litellm_fix_management_v1_get_flat_params
Aug 9, 2026
Merged

fix(proxy): restore management_v1 query-param validation under fastapi>=0.140.7#35773
yuneng-berri merged 2 commits into
BerriAI:litellm_internal_stagingfrom
HuanQian571:litellm_fix_management_v1_get_flat_params

Conversation

@HuanQian571

@HuanQian571 HuanQian571 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • fastapi>=0.140.7 removed get_flat_dependant()
  • importing it broke management_v1/common.py
  • every /management/v1 route went down on that fastapi

How it solves it:

  • switch to the still-present get_flat_params()
  • filter to ParamTypes.query to keep the old behavior
  • unknown-query-param rejection works across fastapi versions

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

get_flat_dependant() exists through fastapi 0.140.6 and is gone from 0.140.7 onward, while get_flat_params() has been present since well before that, so the runs below use a fastapi 0.141.1 interpreter to reproduce the breakage and confirm the fix. This fix touches only route wiring and never calls an LLM, so there is no real-dollar inference request to show; the proof instead drives the actual spend_logs route with a real HTTP request (no mock of the guard under test) and only overrides auth so the request can reach the query-param guard

Before, at 4b7adab548 (base, pre-fix) under fastapi 0.141.1: the module fails to import, so every route depending on it fails to register

$ python -c "import fastapi; print(fastapi.__version__)"
0.141.1
$ python -c "from fastapi.dependencies.utils import get_flat_dependant"
Traceback (most recent call last):
  File "<string>", line 6, in <module>
    from fastapi.dependencies.utils import get_flat_dependant
ImportError: cannot import name 'get_flat_dependant' from 'fastapi.dependencies.utils' (C:\Python313\Lib\site-packages\fastapi\dependencies\utils.py)

After, at da443d1266 (this branch) under fastapi 0.141.1: the module loads and the real /management/v1/spend_logs/end_users route rejects an unknown query param with an RFC 9457 problem before touching the database

$ python -c "from litellm.proxy.management_endpoints.management_v1 import common; print('loaded under', __import__('fastapi').__version__)"
loaded under 0.141.1

$ curl -sS --globoff 'http://0.0.0.0:4000/management/v1/spend_logs/end_users?filter[startTime][gte]=2026-07-23T00:00:00Z&filter[startTime][lte]=2026-07-24T00:00:00Z&bogus=1' \
    -H 'Authorization: Bearer sk-1234'
HTTP 400  content-type: application/problem+json
{
  "type": "urn:litellm:error:unknown-query-parameter",
  "title": "Unknown query parameter",
  "status": 400,
  "detail": "Unrecognized query parameter(s): bogus.",
  "allowed": [
    "filter[startTime][gte]",
    "filter[startTime][lte]",
    "page",
    "page_size",
    "q"
  ]
}

The allowed set is exactly the route's declared query params, so the ParamTypes.query filter kept path and header params out of it

Type

🐛 Bug Fix

Changes

_declared_query_params in management_v1/common.py used get_flat_dependant(...).query_params to learn which query params a route declared, so reject_unknown_query_params could 400 anything else. fastapi 0.140.7 removed get_flat_dependant, so the module failed to import and took every /management/v1 route with it. This swaps in get_flat_params(dependant), which returns the flat, deduped list of all param kinds, and filters to ParamTypes.query to recover exactly the old query-only set. Dedup that the old skip_repeats=True gave is now handled inside get_flat_params

tests/.../management_v1/test_common.py adds regression coverage: it stands up a route with query, path and header params behind reject_unknown_query_params and asserts a declared query alias is accepted, an unknown one is a 400 problem, and path or header names are not mistaken for declared query params. Dropping the ParamTypes.query filter fails the last group

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

@CLAassistant

CLAassistant commented Aug 4, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR restores /management/v1 query-parameter validation compatibility with newer FastAPI versions.

  • Replaces the removed get_flat_dependant() API with get_flat_params().
  • Filters flattened parameters to query parameters so path and header names remain disallowed.
  • Adds regression coverage for aliases, unknown parameters, parameter kinds, and missing route dependency metadata.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/management_v1/common.py Replaces the removed FastAPI helper while preserving the existing query-only validation behavior.
tests/test_litellm/proxy/management_endpoints/management_v1/test_common.py Adds focused, isolated coverage for accepted aliases, rejected unknown parameters, parameter-kind filtering, and absent route metadata.

Reviews (2): Last reviewed commit: "test(proxy): lock in query-param validat..." | Re-trigger Greptile

@codecov

codecov Bot commented Aug 4, 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 Aug 4, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing HuanQian571:litellm_fix_management_v1_get_flat_params (da443d1) with litellm_internal_staging (4b7adab)

Open in CodSpeed

fastapi 0.140.7 removed get_flat_dependant(), which broke the import in
management_v1/common.py and took down every /management/v1 route. Switch to
get_flat_params() and filter to ParamTypes.query so unknown-query-param
rejection keeps matching the old behavior.
Guards _declared_query_params against a regression in the get_flat_params
migration: the flatten step returns path, query, header and cookie params
together, so a dropped ParamTypes.query filter would wrongly treat path or
header names as declared query params and accept unknown ones. Removing the
filter fails these tests.
@HuanQian571
HuanQian571 force-pushed the litellm_fix_management_v1_get_flat_params branch from 02fd50f to da443d1 Compare August 7, 2026 07:37
@HuanQian571 HuanQian571 changed the title Litellm fix management v1 get flat params fix(proxy): restore management_v1 query-param validation under fastapi>=0.140.7 Aug 7, 2026
@HuanQian571

Copy link
Copy Markdown
Contributor Author

@greptileai

@HuanQian571

Copy link
Copy Markdown
Contributor Author

Hi, @yuneng-jiang
This fixes the get_flat_dependant import in management_v1/common.py that you added in cb78491;
fastapi removed that symbol in 0.140.7. All checks are green and Greptile is 5/5 on da443d1. Could you take a look when you have a moment?

@yuneng-berri

Copy link
Copy Markdown
Collaborator

Great catch. Thanks for this, LGTM

@yuneng-berri
yuneng-berri merged commit ecba48d into BerriAI:litellm_internal_staging Aug 9, 2026
82 of 83 checks passed
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.

3 participants