fix(transport): normalize lifecycle incident failures - #830
Conversation
|
The agent hit an error on its last turn. This PR was created by Reflex. This comment updates in place as the agent works. |
Validated full review decision:
|
Review-and-fix handoffValidated review decision: Fixed findings
Tests added/changed
VerificationDeferred/out of scope: none. |
|
✅ Reflex agent status: Completed The agent completed its work. This PR was created by Reflex. This comment updates in place as the agent works. |
Validated follow-up review decision:
|
|
Additional independent verification at |
|
@gautam-rl Final head |
gautam-rl
left a comment
There was a problem hiding this comment.
Please close this PR. The retry change points the wrong way, and the rest is unrelated scope.
What went wrong. Stainless already retries connect failures and (for most routes) timeouts / protocol errors. That is correct for connect: nothing was sent, always retry. After connect, retry is safe if the call is idempotent, not if we can prove the body was never sent. This PR inverts that: is_safe_transport_retry only allows ConnectTimeout / ConnectError on every request(), so read timeouts, pool waits, and HTTP/2 GOAWAY stop retrying even for GETs and for APIs that already have state-machine protection.
Timeout is not a special "do not retry" class. It just means we do not know if the server finished. If repeating the call cannot change the outcome, retry. If it can, do not.
Direction. Move toward idempotency, not fewer retries. This client already mints Stainless idempotency keys on non-GET; execute already has command_id; enable-tunnel is one-tunnel-per-devbox. Use those so a mid-flight timeout is safe to retry. Denylist only the few non-idempotent body calls (upload stream, execute without command_id). Do not teach the SDK that timeouts are radioactive.
The new APIError contract fields, wait_for_tunnel_ready, and clock/sleep test seams are unrelated to that incident and should not ride along.
If the Aug 16 issue still needs a client change, open a small follow-up later. Do not reuse this branch.
Pull request was closed
Summary
cause/__cause__and prevent unsafe partial-transfer retriesVerification
uv run pytest tests/test_transport_error_contract.py -n 0uv run pytest tests/sdk/devbox/test_interfaces.py tests/sdk/async_devbox/test_interfaces.py -n 0uv run pytest tests/test_client.py -n 0uv run ruff check .uv run ruff format --check .uv run mypy src/runloop_api_clientuv run pyright src/runloop_api_clientuv buildFull repository type checking additionally inspects
docs/conf.py; local docs dependencies (sphinx,sphinx-toolbox) are not installed in the provided environment.