Skip to content

fix(proxy): cleandoc exception docstrings used in OpenAPI ERROR_RESPONSES - #29934

Draft
cursor[bot] wants to merge 1 commit into
litellm_internal_stagingfrom
cursor/ci-autofix-automation-265d
Draft

fix(proxy): cleandoc exception docstrings used in OpenAPI ERROR_RESPONSES#29934
cursor[bot] wants to merge 1 commit into
litellm_internal_stagingfrom
cursor/ci-autofix-automation-265d

Conversation

@cursor

@cursor cursor Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

CI's Check UI API Types Sync started failing on every PR rebased onto main right after #27687 + #29885 landed together; the autofix automation noticed it on hourly cron.

Linear ticket

n/a (CI autofix)

Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review

Screenshots / Proof of Fix

Before the fix, regenerating schema.d.ts from the live spec produced a 12-line diff against the file committed by #29885; running npm run gen:api in ui/litellm-dashboard would surface this every time:

$ git diff --stat ui/litellm-dashboard/src/lib/http/schema.d.ts
 ui/litellm-dashboard/src/lib/http/schema.d.ts | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
$ git diff ui/litellm-dashboard/src/lib/http/schema.d.ts
@@ -43119,13 +43119,13 @@ export interface operations {
              * @description Unified rate-limit error.
              *
-             *     Every rate-limit condition surfaced by litellm — whether it originated from
+             *         Every rate-limit condition surfaced by litellm — whether it originated from
...

After the fix, the same regen is a no-op:

$ cd ui/litellm-dashboard
$ LITELLM_PYTHON="uv run --no-sync python" npm run gen:api
✨ openapi-typescript 7.13.0
🚀 /tmp/litellm-openapi-.../openapi.json → /workspace/ui/litellm-dashboard/src/lib/http/schema.d.ts
$ git diff --stat ui/litellm-dashboard/src/lib/http/schema.d.ts
$ git diff ui/litellm-dashboard/src/lib/http/schema.d.ts
$

Regression tests in tests/test_litellm/proxy/common_utils/test_swagger_utils.py:

$ uv run --no-sync pytest tests/test_litellm/proxy/common_utils/test_swagger_utils.py -v
collected 3 items

tests/test_litellm/proxy/common_utils/test_swagger_utils.py::test_exception_description_dedents_multiline_docstring PASSED
tests/test_litellm/proxy/common_utils/test_swagger_utils.py::test_exception_description_falls_back_to_name_when_no_own_doc PASSED
tests/test_litellm/proxy/common_utils/test_swagger_utils.py::test_rate_limit_error_response_description_is_dedented PASSED

3 passed

Type

🐛 Bug Fix

Changes

swagger_utils.ERROR_RESPONSES was wiring exception.__doc__ straight into each Swagger response description. Python preserves the source-code indentation in __doc__, so any multi-line docstring shows up in the spec as \n Unified rate-limit error.\n\n Every rate-limit condition.... openapi-typescript then writes that into JSDoc verbatim, which doubles the indentation in ui/litellm-dashboard/src/lib/http/schema.d.ts.

Until #27687, none of the litellm exception types in LITELLM_EXCEPTION_TYPES had real multi-line docstrings, so this was latent. #27687 added a 7-line docstring on RateLimitError, and #29885 (which runs gen:api against the same docstring) committed a schema.d.ts whose indentation does not round-trip; every subsequent regen drifts and the sync gate fails.

This PR routes __doc__ through inspect.cleandoc before it lands in the OpenAPI spec, so the description stored in openapi.json is dedented at the source. The fallback to exception.__name__ for exceptions without their own docstring is preserved (we keep __doc__, not inspect.getdoc, so we don't pick up the inherited openai.APIStatusError / Exception strings that would replace 19 other 4xx/5xx descriptions). With the fix in place the committed schema.d.ts round-trips through npm run gen:api unchanged.

Tests:

  • _exception_description dedents multi-line docstrings for RateLimitError
  • _exception_description falls back to the class name when a subclass has no own __doc__ (no inheritance leak)
  • the live ERROR_RESPONSES[429] description starts with Unified rate-limit error. and contains no leading-4-space lines
Open in Web View Automation 

…NSES

The Swagger error descriptions wired up in swagger_utils.ERROR_RESPONSES
were taken straight from exception.__doc__, which preserves the leading
whitespace from the Python source (4 spaces per body line for any
multi-line docstring). openapi-typescript renders that into JSDoc
verbatim, so when RateLimitError grew a real multi-line docstring in
#27687, every regenerated schema.d.ts now has a different indentation
than the file committed by #29885. CI's Check UI API Types Sync flips
back and forth between rebases on any PR that doesn't touch
schema.d.ts itself.

Pass __doc__ through inspect.cleandoc so the description stored in the
OpenAPI spec is dedented at the source. The committed schema.d.ts is
exactly what gen:api now produces, so no schema regen is needed in this
commit; future docstrings on litellm exceptions won't reintroduce the
drift either. Inherited docstrings from openai/Exception are still
ignored (we keep the existing __doc__-not-getdoc fallback to the class
name) so the description of every other 4xx/5xx response stays the
class name like 'AuthenticationError'.

Co-authored-by: Krrish Dholakia <krrish-berri-2@users.noreply.github.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

2 participants