mirror of
https://github.com/Comfy-Org/comfy-python-sdk.git
synced 2026-11-04 23:37:47 +00:00
[PR #213] feat(errors): export RateLimited as a fourth shared bucket and map v2 rate_limited to it #213
Labels
No labels
audit:ai-readiness
audit:community
audit:github
audit:health-scoring
audit:policy
audit:release
audit:supply-chain
effort:medium
effort:small
effort:small
effort:trivial
priority:nice-to-have
priority:nice-to-have
priority:recommended
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-python-sdk#213
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-python-sdk/pull/213
Author: @mattmillerai
Created: 10/9/2026
Status: 🔄 Open
Base:
main← Head:mattmiller/be-19965-export-ratelimited📝 Commits (4)
602b405feat(errors): export RateLimited as a fourth shared bucket and map v2 rate_limited to it5ce9ad2docs(errors): note RateLimited.retry_after can be None; count rate_limited among shared codesda7a435chore: merge main into mattmiller/be-19965-export-ratelimitedcff9382Merge remote-tracking branch 'origin/main' into mattmiller/be-19965-export-ratelimited📊 Changes
10 files changed (+100 additions, -30 deletions)
View changed files
📝
CHANGELOG.md(+5 -0)📝
README.md(+12 -4)📝
src/comfy_low/__init__.py(+2 -0)📝
src/comfy_low/errors.py(+12 -4)📝
src/comfy_sdk/__init__.py(+7 -2)📝
src/comfy_sdk/exceptions.py(+9 -5)📝
src/comfy_sdk/router_exceptions.py(+11 -8)📝
tests/test_error_mapping.py(+33 -3)📝
tests/test_exception_modules.py(+8 -2)📝
tests/test_job_metadata.py(+1 -2)📄 Description
ELI5
When the server says "slow down, you have sent too many requests for now", the SDK already raised a dedicated rate-limit error, but you could only import it from the router-specific module. Now you can import it straight from the SDK's top-level package, the same way the other shared errors already work. It is the same error either way, so code that catches one import also catches the other.
What changed
comfy_sdk.exceptions:RateLimited(re-exported fromrouter_exceptions, the same object) is listed explicitly in_BY_CODEas"rate_limited", besideinsufficient_credits. It is also added to__all__. The comments and docstrings that counted "three" shared buckets now say four.comfy_sdkroot: imports and exportsRateLimited. The__all__comment now says that the four shared buckets are lifted and the Router-only buckets stay inrouter_exceptions.comfy_sdk.router_exceptions: only the module docstring changed, to count four shared names and to describe what the package root exports. The class itself is unchanged.comfy_low.errors: addsclass RateLimited(ApiError): code = "rate_limited", with a docstring that contrasts it withqueue_full, and adds it to_BY_CODE._CODE_BY_STATUS[429] = "queue_full"is unchanged, so a 429 with no code still decodes asQueueFull.test_exception_modules.py: the shared-name and descends-from-both checks now includeRateLimited.test_error_mapping.py:rate_limitedmoved from the Router-only parametrize list totest_a_bucket_both_surfaces_spell_keeps_its_v2_class. Two new tests:to_sdk_error(ApiError("slow down", code="rate_limited", http_status=429, retry_after=3))returns an instance ofcomfy_sdk.RateLimited, which is the same object asexceptions.RateLimitedandrouter_exceptions.RateLimited.retry_afteris 3.error_from_envelope(429, {"error": {"code": "rate_limited", ...}}, retry_after=3)returns acomfy_low.errors.RateLimited, and a 429 with no code still returnsQueueFull.test_job_metadata.pynow importsRateLimitedfromcomfy_sdk, which proves the root export through the existingpytest.raisescases.RateLimitedentry. It says.retry_afterisNonewhen the response sent no delta-secondsRetry-After, because unlikeQueueFull's it is not defaulted to0. Thecomfy_low/errors.pycomments that counted three identically spelled codes now count four. The Router section's shared-names paragraph now counts four. CHANGELOG has a new entry under Unreleased → Added.Judgment calls
comfy_lowroot export. I also exportedRateLimitedfrom thecomfy_lowpackage root. Every other class incomfy_low.errorsis exported there, and the TypeScript low layer is meant to mirror this one.rate_limitedresponse, or a v2 one, now becomescomfy_low.errors.RateLimitedat the low layer instead of a bareApiError. It is still anApiErrorsubclass, and I found nothing insrc/that checkstype(exc) is ApiErroror relies on that code being untyped._class_foralready resolvedrate_limitedto this class through the_BY_ERROR_TYPEfallback. Listing it in_BY_CODEdocuments the mapping rather than changing it, so removing the_BY_CODEentry would not fail the new SDK test. The test pins the outcome, not which lookup produced it.Provenance
cff9382, after mergingmainat3fa8ac1)pytest -qgives 1277 passed and 9 skipped. The skips include the env-gated gateway e2e.ruff check .,ruff format --check .andmypy srcare clean.scripts/check_drift.pyis OK: models are in sync, and all 20 Router error types are covered and blessed.scripts/check_public_repo_hygiene.pyis OK.build-check. CI runs both on push.comfy_lowroot export described above. The CHANGELOG entry sits under Unreleased → Added, next to theResultExpiredentry thatmainadded while this PR was open.Residual
sso_required→Forbidden(#205) also editssrc/comfy_sdk/exceptions.pyandsrc/comfy_low/errors.py. Whichever lands second needs a rebase, which should be mechanical: different_BY_CODEentries and adjacent comment lines. The HEAD-429rate_limitedPR (#208) edits onlycomfy_low/transport.py. Its bodiless HEAD probe will produce the newcomfy_low.errors.RateLimited/comfy_sdk.RateLimitedonce both are merged, but I did not exercise that combination here.RateLimitedexport, and itssurface-parity.test.tscheck, are a separate follow-up that this PR unblocks. That repo was not touched or run here.Summary by CodeRabbit
RateLimitedexception for rate-limit responses, available from the SDK and low-level package.QueueFull.RateLimitedrelates to other workflow and Router errors, and documented itsretry_afterattribute.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.