Repository navigation
Retry HTTP 429 and 5xx responses for queries and mutations - #102
Merged
Merged
Conversation
Queries bail on any HTTP error and mutations retry every HTTP error, including 4xx, and surface graphql-request's raw ClientError. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
API Gateway returns an occasional 503 when its Lambda invoke stalls. The query path passed every ClientError to bail(), so a balance read failed on the first attempt. Both operation types now send the request through one path: 429/5xx throws a FragmentError so async-retry retries it, any other status bails with the same FragmentError. Mutations previously let the raw ClientError escape and retried 4xx responses too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A connection reset or DNS failure is as transient as a 503. Errors that are not a ClientError propagate out of the retry callback so async-retry retries them, and the last one is what the caller sees. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
omichowdhury
force-pushed
the
fix-retry-http-errors
branch
from
October 22, 2026 16:10
ae94e49 to
d01de99
Compare
Each attempt resolves to either data or an error tagged retryable, so the retry callback has one throw site, one bail site and no fall-through after bailing on a multi-key mutation response. The mutation payload is typed instead of cast through `any`, and the unknown-operation-type guard runs before retry() starts. Tests await the rejection matchers directly instead of capturing the error with `.catch`, share one `makeClient`, and cover a mutation that succeeds after two 503s. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A rejection that is not a ClientError is retried only when it is node-fetch's FetchError of type "system". An AbortError or a bug in the SDK surfaces on the first attempt instead of after the backoff. FragmentError.cause now admits the mutation error payload it has always carried at runtime, so client.ts no longer launders it as an Error. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Attempts are counted at the mock server instead of through onRetry, so the tests exercise DEFAULT_RETRY_CONFIG as shipped. The README Retries section is dropped; the defaults are what callers get. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
omichowdhury
marked this pull request as ready for review
October 27, 2026 17:09
vigneshwerv
approved these changes
Oct 27, 2026
vigneshwerv
left a comment
Contributor
There was a problem hiding this comment.
One nit: Could you refactor out the ternary statements?
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
Author
|
Ternaries replaced with 🤖 Claude Code |
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.
The SDK's retry wrapper only retried GraphQL-level
retryableerrors on mutations. A query hitting an HTTP 503 (API Gateway timing out its Lambda invoke) failed on the first attempt, which is how a customer saw a 503 on a balance read.retryConfig; other statuses throw aFragmentErrorimmediately.ClientError. They now surfaceFragmentErrorwithstatuslike queries.AbortError) are not retried.FragmentError.causeis now typed to include the mutation error payload it already carried.🤖 Generated with Claude Code