BerriAI/litellm · warning · ManagementProblem

urn:litellm:error:unknown-query-parameter

urn:litellm:error:unknown-query-parameter

Error message

Unrecognized query parameter(s): {', '.join(unknown)}.

What it means

The same unknown-query-parameter problem, raised from the shared list framework: handle_list() first builds a query plan via build_query_plan, which returns a ProblemDetail when it finds query names outside the spec's allowed set (including the route's scoping params), and line 515 converts that plan-problem into a ManagementProblem. Every /management/v1 list endpoint built on handle_list (budgets, keys, teams, ...) funnels through this single raise.

Source

Thrown at litellm/proxy/management_endpoints/management_v1/list_framework.py:515

        take=page_size,
    )


def _duplicate_params(request: Request) -> tuple[str, ...]:
    names: Final = tuple(name for name, _ in request.query_params.multi_items())
    return tuple(sorted(frozenset(name for name in names if names.count(name) > 1)))


async def handle_list(
    spec: ListSpec[TRow, TOut],
    executor: ListExecutor[TRow],
    request: Request,
    caller: UserAPIKeyAuth,
) -> ListResponse[TOut]:
    """Plan, execute, count, serialize, envelope. Failures reach the client as RFC 9457 problems."""
    plan: Final = build_query_plan(spec=spec, params=request.query_params, caller=caller)
    if isinstance(plan, ProblemDetail):
        raise ManagementProblem(plan)

    # Checked here rather than in build_query_plan because a Mapping[str, str] cannot
    # represent a repeat: query_params.get() silently keeps the last one, so ?page=1&page=999
    # would page from 999 without the caller ever being told which value won.
    duplicates: Final = _duplicate_params(request)
    if duplicates:
        raise ManagementProblem(
            _problem(
                "duplicate-query-parameter",
                "Duplicate query parameter",
                400,
                f"Repeated query parameter(s): {', '.join(duplicates)}. Each may appear once; "
                f"use a comma-separated list for multiple sort keys or filter values.",
            )
        )

    total_count: Final = await executor.count(plan.where)
    rows: Final = await executor.find_many(plan)

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Send only parameters the endpoint declares: page, page_size, sort (comma-separated, '-' prefix for descending), search, and filter[<field>][op] names from its spec
  2. Read the problem's detail — it lists the unknown names and the allowed set for that exact route
  3. Pin your client SDK to a version matching the proxy release so allowed sets agree
  4. Never repeat a parameter (?page=1&page=2) — that raises the related duplicate-query-parameter 400 from the same handler

Example fix

# before
curl 'http://localhost:4000/management/v1/keys?sort_dir=asc'   # 400 via handle_list
# after
curl 'http://localhost:4000/management/v1/keys?sort=-token&page_size=25'
Defensive patterns

Strategy: validation

Validate before calling

from collections import Counter

def validate_list_query(q: dict) -> None:
    ALLOWED = {'page', 'page_size', 'sort', 'search'}  # per-route allowlist
    unknown = set(q) - ALLOWED
    if unknown:
        raise ValueError(f'unknown params {sorted(unknown)}; allowed {sorted(ALLOWED)}')
    dupes = [k for k, n in Counter(q).items() if n > 1]  # only relevant if you build raw query strings
    if dupes:
        raise ValueError(f'params may appear once: {dupes}; use comma-separated values instead')

Try / catch

try:
    r = await client.get('/management/v1/keys', params=q)
    r.raise_for_status()
except httpx.HTTPStatusError as e:
    problem = e.response.json()
    ptype = problem.get('type', '')
    if ptype.endswith('unknown-query-parameter'):
        q = {k: v for k, v in q.items() if k in ALLOWED}  # strip and retry once
        r = await client.get('/management/v1/keys', params=q)
    elif ptype.endswith('duplicate-query-parameter'):
        raise ValueError('send each param once; join multi-values with commas') from e
    else:
        raise

Prevention

When it happens

Trigger: Any management/v1 list call with an undeclared parameter, e.g. ?sort_dir=asc instead of sort=..., ?model=gpt-4o on a route without a model filter, or a caller trying to override a server-scoped param like user_filter that only admins can set; also fires when params pass the route-level check but not the per-spec allowed set.

Common situations: Clients targeting params documented for a different list endpoint; assuming OpenAI-style pagination names (limit/offset) instead of page/page_size; version drift between the SDK's query builder and the deployed spec.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/bdc921fa9c55c95b. Report an issue: GitHub.