You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Transport: httpx network errors (ConnectError/NetworkError/etc.) never retry, even for GET/HEAD/OPTIONS #240
Transient ECONNRESET, DNS hiccups, HTTP/2 RST_STREAM, server half-closes, and TCP connect refusals on a safe idempotent GET (markets list, portfolio snapshot, etc.) surface as a one-shot failure to the caller. The retry loop only handles TimeoutException and PoolTimeout; every other httpx.HTTPError subclass lands in a final except and re-raises with no retry.
Industry-standard SDKs (openai-python, anthropic-python, stripe-python, urllib3) all retry idempotent verbs on transport-level errors. ConnectError on POST is in principle also safe to retry (request never reached the wire, mirroring the PoolTimeout reasoning from #204).
Location
kalshi/_base_client.py:284-286 — sync transport final except httpx.HTTPError
kalshi/_base_client.py:466-467 — async transport mirror
Evidence
excepthttpx.HTTPErrorase:
raiseKalshiError(f"HTTP error: {method.upper()}{path}") frome# httpx hierarchy: ConnectError/NetworkError/RemoteProtocolError/ReadError/WriteError# all inherit from TransportError -> RequestError -> HTTPError.
Recommended fix
Insert an except httpx.TransportError (or split out ConnectError/NetworkError/RemoteProtocolError/ReadError/WriteError) between TimeoutException and HTTPError that participates in the same RETRYABLE_METHODS + backoff + total_timeout budget loop. Mirror the PoolTimeout "never reached the wire" branch for ConnectError so POST/DELETE can retry only on pre-wire failures.
Activity
fix(transport): retry idempotent verbs on httpx transport errors; add…
fix(transport): retry idempotent verbs on httpx transport errors; add…