fix(router): treat malformed configured token limits as absent on /v1/models - #33864
Conversation
…/models A deployment whose model_info carried a non-numeric max_input_tokens or max_output_tokens (for example "128,000" or an empty string) made the bare int() in get_configured_token_limits raise inside the per-model /v1/models loop, so one misconfigured deployment turned the entire listing into a 500. Coerce each configured limit safely and treat malformed values as absent, matching the graceful degradation the listing had before the cost-map switch
…itellm_tokenlimits_guard
Greptile SummaryThis PR hardens
Confidence Score: 5/5Safe to merge — the change is narrowly scoped to a safe-coercion wrapper in a single method, restoring graceful degradation for misconfigured token limits without altering any other behavior. The fix is minimal and correct: the No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/router.py | Adds safe _as_int coercion inside get_configured_token_limits; logic is correct, bool guard is properly placed before int(), and malformed values correctly return (None, None). |
| tests/test_litellm/test_router.py | Two new unit tests cover all targeted malformed-value shapes and the numeric-string coercion path; no real network calls. |
| tests/test_litellm/proxy/test_proxy_utils.py | New integration test exercises the full create_model_info_response path with a real Router and malformed limit, confirming the response returns without exception and omits the bad limit fields. |
Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…mplete the 1.93.0 stable cut (#33869) * fix(docker): bake prisma CLI and engines at a fixed path so fresh-DB migrations work for any uid offline (#33853) * fix(docker): bake prisma CLI and engines at a fixed path so fresh-DB migrations work for any uid offline The runtime image shipped the prisma CLI and engines under /root/.cache, the default HOME-derived prisma-python cache location. Any deployment whose runtime HOME is not /root (kubernetes runAsUser, docker --user, HOME overrides) missed that cache on a fresh database, fell back to a nodeenv Node download that crashes on Wolfi (libatomic.so.1), and started the proxy with zero tables while every DB-backed endpoint returned 500 The bake now lives at /opt/prisma, a path no HOME resolution or cache volume mount can shadow. The builder records the engine paths there at generate time, and the runtime stage pins PRISMA_BINARY_CACHE_DIR, PRISMA_CLI_PATH, PRISMA_CLI_QUERY_ENGINE_TYPE=binary and PRISMA_OFFLINE_MODE so both litellm-proxy-extras and prisma-python resolve the baked CLI and engines directly. prisma migrate deploy on a fresh database now needs no npm and no network access for any runtime uid, including readOnlyRootFilesystem deployments Verified against live containers: fresh and existing databases as root, uid 12345, HOME overridden, on an internal-only docker network, and with a read-only root filesystem all migrate and serve /team/new successfully Fixes #33650, #24554 * chore(docker): fail the image build if the baked prisma CLI layout drifts Asserts the baked CLI shim is executable and its entrypoint exists in the runtime stage after the COPY and chmod, so a layout change in a future prisma-python release breaks the image build loudly instead of silently degrading the migration path at container startup (cherry picked from commit 567ebcb) * fix(router): treat malformed configured token limits as absent on /v1/models (#33864) A deployment whose model_info carried a non-numeric max_input_tokens or max_output_tokens (for example "128,000" or an empty string) made the bare int() in get_configured_token_limits raise inside the per-model /v1/models loop, so one misconfigured deployment turned the entire listing into a 500. Coerce each configured limit safely and treat malformed values as absent, matching the graceful degradation the listing had before the cost-map switch (cherry picked from commit ef7007c)
Relevant issues
Hardening follow-up to #33721. That change sources /v1/models token limits from the cost map with a per-deployment configured-limit override, but the override path ran a bare int() on the admin-configured model_info values. A single deployment configured with a non-numeric limit (for example "128,000", an empty string, "unlimited", or a YAML list) made the conversion raise inside the per-model listing loop, so the entire GET /v1/models response returned 500, taking well-formed sibling models down with it. Before #33721 the same configuration degraded to a response without limits, so this restores that contract while keeping the O(1) lookup and the configured-limit override
Linear ticket
Pre-Submission checklist
@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Live proxy with this model_list entry in the config:
Before, at
d495da4ce4(staging tip without this fix):After, same request with the fix applied (captured at the PR commit):
Both new regression tests fail on the pre-fix code with the exact defect (
ValueError: invalid literal for int() with base 10: '128,000'at litellm/router.py) and pass with itType
🐛 Bug Fix
Changes
Router.get_configured_token_limits now runs each configured limit through a safe int coercion: None, bools, and values that raise TypeError/ValueError on int() are treated as absent instead of propagating out of the /v1/models listing loop. Numeric strings (a YAML-quoted "32000") still coerce, and well-formed integer configs are unchanged. The docstring now states the malformed-value contract
Tests: test_get_configured_token_limits_treats_malformed_values_as_absent pins (None, None) for the malformed shapes at the Router level, test_get_configured_token_limits_coerces_numeric_strings pins the tolerant path, and test_create_model_info_response_survives_malformed_configured_limits exercises the full /v1/models enrichment with a real Router and asserts the base response comes back instead of an exception
Final Attestation