⚠️ stream error: error sending request for url (https://chatgpt.com/backend-api/codex/responses); retrying 1/5 in 182ms…
The verb is “sending”, and that single word rules out most of what you would
otherwise check. The request never reached the endpoint, so no HTTP response
ever existed — which means this cannot be an authentication failure, a quota
rejection, a rate limit or a model overload. All four of those are responses,
and they arrive with a status, a type and a code. You got none of that,
because nothing on the other end formed an opinion. Something between your
process and that URL failed while the request was still on its way out.
The URL is the most useful thing in the message
Most streaming errors describe a symptom. This one names a destination, and that turns a vague network complaint into a set of checks you can actually run: hostname resolution, TLS handshake, proxy policy, route.
Start with the hostname, because it is not the one people assume. The host in
this message is chatgpt.com. The platform API that the official SDKs talk to
lives on api.openai.com — a different name, resolved separately, presented
under its own certificate, and subject to its own treatment by whatever sits in
your network path.
Three consequences follow, and each of them is a test:
- A network policy that allows one host does not allow the other. Corporate proxy allowlists, DNS filters and TLS-inspecting appliances are configured per hostname. An allowlist entry for the API host will not cover this one, and the symptom is exactly this: everything else works, this one path fails.
- Reachability is testable directly. Resolve the hostname from the affected machine and open a TLS connection to it. A failure at either step is your answer and has nothing to do with any AI tooling.
- Platform status is the wrong first stop. An incident affecting one front door is not automatically an incident on the other, and the reverse is also true. Confirm your own path is intact before you go looking for an outage to blame.
The retry counter is not evidence of an outage
Here is the judgment worth the page. A client that exhausts a small number of attempts with sub-second gaps has not proven the service is unavailable. It has proven the service was unavailable for about a second.
Look at the delay printed in your own copy of the message — the interval before the next attempt is a fraction of a second. Even with backoff, a handful of attempts spaced like that can be spent in well under the time it takes a recovering network to become usable again. A Wi-Fi network re-associating, a VPN tunnel re-establishing, a laptop bringing its interfaces back up after sleep, a DNS cache repopulating: every one of those takes longer than the client is willing to wait.
So a run of attempts ending in a hard failure, immediately after any network transition, is a statement about the client’s patience rather than about the platform. The correct response is to wait a few seconds and issue one manual attempt. If that succeeds, nothing was ever wrong with the service and nothing needs fixing.
One related warning: do not treat the numbers inside the message as constants to tune against. The attempt count and the delay are values your client chose and printed; they are not published API behaviour, and they will not necessarily be the same in your next occurrence.
The single-failure-then-success pattern
If the first attempt fails and the next one succeeds instantly, you are almost certainly looking at a dead connection being discovered rather than a network being down.
HTTP clients keep connections alive and reuse them. When a machine sleeps, changes networks, or switches interfaces, the socket in that pool survives as an object in memory while the route underneath it is gone. The next request goes out on a connection that no longer leads anywhere and fails on the send leg — producing exactly this message. The retry opens a fresh connection and works.
That is the failure doing its job. There is no misconfiguration behind it and no fix to apply, and a page of proxy tuning would be wasted on it. If this only ever happens as the first request after a resume or a network change, and always clears on the following attempt, stop investigating.
Is retrying useful?
Yes — and the client is already doing it, so the real question is what the pattern means.
Attempt one fails, attempt two succeeds. Transient, almost always a stale connection. No action.
All attempts fail within a second or two, then it works later. The client outran the network’s recovery. Pause, retry once by hand, and judge from that.
All attempts fail, and a manual retry a minute later also fails. This is a genuine reachability problem, and it is the only branch where the sections above turn into real work. Test resolution and TLS to the host directly before you touch any tool configuration.
It fails from one network and succeeds from another. The path is the cause. Nothing you change in your client will out-argue an appliance that is refusing the connection.
When retrying does not terminate, stop the loop rather than letting it run. Failed requests still count against your per-minute limits, and a client hammering an unreachable host is generating load without generating information. Note also that nothing below you retries a stream that has already started delivering output: the official Python client documents that stream consumption is not automatically retried, because replaying a request could duplicate output already delivered to your application. The retry you are watching here is possible precisely because no output had arrived yet.
Telling the causes apart
Did output already arrive before this appeared? Then you are on the wrong page. This error belongs to the send leg; a failure after tokens were flowing is a mid-stream teardown, and the message will name an event or a byte shortfall rather than a URL. Start with stream closed before response.complete instead.
Does it coincide with sleep, VPN toggles, or Wi-Fi changes? Reproduce deliberately: put the machine to sleep, wake it, and immediately issue a request. If the failure follows the trigger reliably, you have identified it and it is benign.
Does it happen only on a corporate network? Test the same workload from a different path. TLS interception and hostname allowlists are the two mechanisms that break one host and leave others working.
Does it happen on every request from a clean network? Then it is neither stale connections nor policy. Check resolution first, and only then consider a platform-side problem.
Does the same failure appear wrapped in a summarisation step? The compaction path is the largest request in a session and fails first on a marginal connection; see Error running remote compact task.
Fix by scenario
- Single failure after a network transition — nothing. Understand it and move on; this is the majority case.
- Attempts exhausted in a second, works later — wait, then make one manual attempt. Treat the exhausted burst as a timing artefact, not a diagnosis.
- Persistent, one network only — take it to whoever runs that network, with the hostname from the error message. That name is the whole ask: they need to allow it, and they cannot act on “the AI tool is broken”.
- Persistent everywhere, resolution and TLS both fine — now platform status is a reasonable check, and a report is reasonable to file.
- Intermittent during long sessions with output flowing — this is not your error. The framing failures in this cluster are diagnosed by measurement, not by hostname; see Response payload is not completed.
How to confirm it’s fixed
Reproduce the trigger rather than waiting for the error to come back. If sleep and resume produced it, sleep and resume again, then issue a request and require it to succeed on the first attempt, twice in a row. Requiring the first attempt is the whole point: a retry that succeeds tells you the retry works, not that the underlying condition is gone.
If the cause was network policy, confirm at the layer you changed. Resolve the hostname and complete a TLS handshake to it from the affected machine, then run a real request. A tool that works while the direct connection test still fails means you are succeeding through some other route and the original problem is still there, waiting.
Related errors
The neighbours in this cluster differ by how far the request got. When the request arrived and the response ended without its completion event, read stream closed before response.complete. When an error body came back but could not be deserialized, the second failure is hiding the first, and that is failed to parse ErrorResponse — worth reading here because an unparseable error body is a sign that something other than the platform answered, which is the same suspicion a hostname problem raises. If you cannot tell which of them you are holding, the AI coding error triage tool sorts them by the signals used above: whether any output arrived, whether a response existed at all, and whether the failure follows your network rather than your workload.