Skip to content

Retry: include Cloudflare 5xx (520–524) and 408 in RETRYABLE_STATUS_CODES #192

Description

@TexasCoding

Summary

RETRYABLE_STATUS_CODES = {429, 500, 502, 503, 504} omits the Cloudflare-origin transient 5xx range. Kalshi's production endpoint (api.elections.kalshi.com) is fronted by Cloudflare; brief origin blips surface as 520 (Unknown Error), 521 (Web Server Down), 522 (Connection Timed Out), 523 (Origin Unreachable), 524 (A Timeout Occurred), 525 (SSL Handshake Failed), and are designed to be retried by clients.

Today the SDK maps them to KalshiServerError (via the status >= 500 branch at _base_client.py:71) but fails fast instead of retrying — a production trader polling markets.get_orderbook() will see avoidable hard failures whenever the CDN→origin link has a hiccup during market-open bursts.

Standard codes also worth widening: 408 Request Timeout and 425 Too Early are both safe to retry on idempotent verbs.

Location

kalshi/_base_client.py:31

Evidence

# kalshi/_base_client.py:31
RETRYABLE_STATUS_CODES = {429, 500, 502, 503, 504}
# DELETE excluded: cancel/batch_cancel are not safely idempotent
RETRYABLE_METHODS = {"GET", "HEAD", "OPTIONS"}

Recommended fix

RETRYABLE_STATUS_CODES = {408, 425, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524}

Idempotency is preserved by the unchanged RETRYABLE_METHODS set — POST/DELETE still never retry, even on 521. Add tests:

  • test_521_retried_on_get — GET → 521 → 521 → 200 succeeds.
  • test_521_raised_on_post — POST → 521 raises KalshiServerError with status 521 (no retry).
  • Parametrize over the new codes to lock in the policy.

Severity & category

high / correctness

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginfraInfrastructure/tooling

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions