Repository navigation
Fix 5xx/429 retries in api_client so they actually fire, with backoff - #228
Open
cx-happy-yang wants to merge 2 commits into
Open
cx-happy-yang wants to merge 2 commits into
cx-happy-yang wants to merge 2 commits into
Conversation
check_response() was called inside call_api() before the @Retry decorator could inspect the response, so the 500/502/503/504 and 429 retry branches were dead code — every server error raised ValueError on the first attempt with zero retries (verified against customer logs on 1.9.1: 504 gateway timeout on SCA report export). Move check_response() into the retry wrapper, after the retry decision: - 500/502/503/504: honor Retry-After header when present, otherwise exponential backoff (5s, 10s, 20s, ... capped at 30s), retry up to max_retries, then raise the usual ValueError format on exhaustion. - 429: same treatment — Retry-After first, then exponential backoff (60s base, capped at 300s). - Non-retryable statuses (e.g. 404) still raise immediately, and success responses pass through unchanged. Adds tests covering 504 retry-with-backoff, growing backoff, Retry-After, exhausted-retries raising, 429 Retry-After, and 4xx non-retry. Co-Authored-By: Claude Code <noreply@anthropic.com>
Moves the Unreleased entries (CxOne export renames and the api_client 5xx/429 retry fix) under a 1.9.2 release section. Co-Authored-By: Claude Code <noreply@anthropic.com>
cx-nathan-leach
approved these changes
Oct 27, 2026
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.
check_response() was called inside call_api() before the @Retry decorator could inspect the response, so the 500/502/503/504 and 429 retry branches were dead code — every server error raised ValueError on the first attempt with zero retries (verified against customer logs on 1.9.1: 504 gateway timeout on SCA report export).
Move check_response() into the retry wrapper, after the retry decision:
Adds tests covering 504 retry-with-backoff, growing backoff, Retry-After, exhausted-retries raising, 429 Retry-After, and 4xx non-retry.
Problem
Customers on 1.9.1 still get 504 gateway timeouts (SCA report export) with zero retries. Traceback verified against tag
b2e0095:api_client.py:271 in call_api -> check_response(response)
api_client.py:204 in check_response -> raise ValueError
ValueError: ('HttpStatusCode: 504', 'ErrorMessage: {"message": "Endpoint request timed out"}')
Root cause:
check_response()was called insidecall_api()before the@retrydecorator could inspect the response, so the 500/502/503/504 and 429 retry branches in the decorator were dead code — every server error raised on the first attempt.Fix
Move
check_response()into the retry wrapper, after the retry decision:Retry-Afterheader when present, otherwise exponential backoff (5s, 10s, 20s, ... capped at 30s), retry up tomax_retries, then raise the usualValueErrorformat on exhaustion.Retry-Afterfirst, otherwise exponential backoff (60s base, capped at 300s).Tests
Six new tests in
TestServerErrorRetrycovering: 504 retry-with-backoff then success, growing backoff (5s then 10s),Retry-Afterhonored, exhausted retries raising the expectedValueError, 429 withRetry-After, and 4xx raising without retry.tests/test_api_client.py: 13/13 pass.