Repository navigation
feat(errors): export RateLimited as a fourth shared bucket and map v2 rate_limited to it - #213
Open
mattmillerai wants to merge 3 commits into
Open
mattmillerai wants to merge 3 commits into
mattmillerai wants to merge 3 commits into
Conversation
… rate_limited to it The v2 job routes document rate_limited with the same spelling Router uses. to_sdk_error already raised router_exceptions.RateLimited for it through the _BY_ERROR_TYPE fallback, but the class was reachable only from comfy_sdk.router_exceptions. Lift it beside Unauthorized, Forbidden and InsufficientCredits: list it in exceptions._BY_CODE, export it from comfy_sdk.exceptions and the package root, and add comfy_low.errors.RateLimited for the low layer. The code-less 429 -> queue_full fallback is unchanged.
There was a problem hiding this comment.
🔍 Cursor Review — Consolidated panel
Triggered by @mattmillerai.
Found 2 finding(s).
| Severity | Count |
|---|---|
| 🟢 Low | 1 |
| ⚪ Nit | 1 |
Panel: 6/6 reviewers contributed findings.
…mited among shared codes The README bullet said RateLimited carries .retry_after seconds, but it is passed through as-is and is None without a delta-seconds Retry-After header, unlike QueueFull which defaults it to 0. Two comments in comfy_low/errors.py still named three identically spelled codes; rate_limited is the fourth.
Resolve the CHANGELOG conflict: main cut 0.5.0, so the RateLimited entry moves under [Unreleased] / Added.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ELI-5
When the server tells you "slow down, you've used up your request allowance for now" (
rate_limited), the SDK already raised aRateLimitedexception, but you could only import it fromcomfy_sdk.router_exceptions. Nowfrom comfy_sdk import RateLimitedworks too, the same wayUnauthorized,ForbiddenandInsufficientCreditsalready do. It is the same class object, so anexceptwritten against either import catches the error.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
da7a435, after mergingmainat6d2dd72)pytest -qgives 1267 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 the 19 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 a fresh Unreleased → Added, becausemaincut 0.5.0 while this PR was open.Residual
sso_required→Forbidden(feat(errors): map sso_required to Forbidden and carry organization_id #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 (fix(assets): read a bodiless HEAD 429 on the by-hash probe as rate_limited, not queue_full #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.