Codex stream disconnected before completion: Diagnose the Cause

Trace Codex stream disconnects using the full error, response events, session history and network path without blindly retrying unfinished tool actions.

Warm gray cover with a light paper panel, a line drawing of an electrical plug and cord, geometric accents and the title Codex Stream Errors.

stream disconnected before completion tells you that a Codex response did not finish as expected. It does not identify one universal cause. Read the rest of the error, check whether the transport was SSE or WebSocket, and distinguish an explicit quota or context error from a connection that closed before the completion event arrived.

Before retrying, inspect any files the agent changed and any actions its tools performed. A disconnected response does not mean that earlier commands were rolled back. This guide is for Codex users and developers operating compatible Responses endpoints. It is based on official documentation and source inspection on September 14, 2026. We have not reproduced your specific incident.

If a new desktop task never reaches its first reply and the full error says application network permission was revoked, use the Codex task-startup and network-permission guide. Record that exact error before treating the incident as a response stream that began and then disconnected.

Classify the suffix, not just the headline

The current Codex SSE parser distinguishes an unfinished stream from more specific recorded errors. Its generic closed-before-completed fallback is not evidence that the user’s internet connection was necessarily responsible.

ObservationWhat it establishesFirst investigation
Closed before response.completedNormal completion was not observedTransport, server and intermediary logs
response.failed with a codeProvider reported a specific failureThe actual code and error message
response.incompleteAn explicit incomplete event arrivedincomplete_details.reason
SSE idle timeoutNo SSE event arrived within the configured idle windowUpstream delays and intermediary timeouts
WebSocket closed by serverA WebSocket close was observedRoute support and close details

A readable partial answer is not proof that the response completed. In the streaming documentation, text events and response lifecycle events serve different purposes. response.output_text.done ends a text portion; it should not be treated as a substitute for the overall response completion signal.

Preserve work before repeating the task

Review the current diff, terminal output and any external action that was started. A tool can finish while the final model response fails to reach the interface. For actions with side effects, check the destination or execution record before asking the agent to repeat them.

Do not assume that an automatic retry gives exactly-once execution or that a failed-looking request is free. Those guarantees depend on the operation and provider. When continuing a coding task, describe what has already been verified and what remains uncertain so that the next attempt does not blindly rerun every step.

For a controlled diagnostic, use a new session and a short read-only task. Keep the model and route unchanged at first. If that succeeds while the original session fails, history length, compaction or a tool sequence becomes worth inspecting. It does not by itself prove a particular client bug.

Handle explicit errors on their own terms

The official API error guide separates authentication, access, rate limits and server failures. Check the response body rather than treating every failed stream as a retryable network issue.

A missing model or wrong route belongs in the model-not-found guide. A subscription allowance is different from API billing balance and from a rate limit measured over time. For account-window questions, see the Codex limit guide. Do not solve a named quota error by repeatedly increasing a network timeout.

Likewise, context_length_exceeded points to a different constraint from an idle connection. Reduce or manage the relevant context using supported client features and preserve important task state. A new empty conversation may diagnose the difference, but it is not a substitute for understanding which history the original request contained.

WebSocket closed before response.completed: a diagnostic walkthrough

For the exact error stream disconnected before completion: websocket closed by server before response.completed, start with the checks below. The missing completion event describes what the client observed; it does not identify which system closed the connection or whether an earlier tool action succeeded. This walkthrough is a diagnostic procedure, not a claim that we reproduced your outage. Documentation was checked again on October 15, 2026.

1. Record the client and protect work already done

In the project terminal, run these read-only commands:

codex --version
git status --short
git diff --stat

The first prints the installed CLI version. The other two summarize tracked changes and untracked paths in a Git working tree; they do not establish whether an external action completed. If the directory is not a Git repository, inspect the relevant files and execution records directly instead of initializing a repository just for this check. Review any important changes before restarting or repeating the task.

In an interactive Codex session, run /status to check the active session details. Record the selected model and provider separately if they are not shown. The CLI you invoke in a terminal may differ from the runtime used by a desktop application or editor extension. Record the surface that actually failed, not just whichever binary happens to be first on your PATH.

Save the full error, the failure time with timezone, and the last operation you can confirm completed. A partial answer or a successful shell command is not evidence that the entire response finished. Conversely, a failed response is not permission to rerun a deployment, payment or other external write.

2. Capture a small, relevant log excerpt

Use the failing client’s diagnostics first. For a local CLI, the current configuration reference documents log_dir; setting it explicitly enables the optional plaintext TUI log codex-tui.log. An absent plaintext file alone does not prove that Codex never ran. Check your installed version before relying on a setting from newer documentation.

If you need a new diagnostic capture, create a private local directory and set log_dir to its absolute path in the configuration used by that client. For example, on macOS or Linux, replace the example path with your own:

# Local diagnostic directory; this is not a provider setting.
log_dir = "/absolute/private/path/codex-stream-diagnostics"

On Windows, a TOML literal string such as log_dir = 'C:\Users\YOUR_NAME\codex-stream-diagnostics' avoids backslash escaping. Do not duplicate an existing key. Place this root-level setting before table headers such as [model_providers.example], otherwise it may belong to the wrong table. Keep the previous configuration so you can restore it after the capture. Restart only your affected client when appropriate; do not restart a shared server with other active work merely to obtain a log.

Reproduce with a harmless task, then inspect the excerpt around the recorded time. Look for the complete error suffix, a request or response ID if available, an explicit upstream error, and the last response event. Plaintext logs can contain prompts, paths or tool details. Review and redact the excerpt locally before sharing; do not upload the entire log directory or authentication files.

3. Change one variable and record the result

Use a fresh session with the same model, account and route. A suitable control prompt is:

Reply with exactly READY. Do not call tools or inspect files.

This sends an inference request and may consume your allowance or incur API charges. It is a small diagnostic task, not a free connectivity probe. Do not repeat it in an unlimited retry loop. Record whether it ended normally, the elapsed time, and the exact error if it failed.

Controlled observationWhat to investigate nextWhat it does not prove
The short fresh session succeeds; the original failsOriginal history, compaction, tool sequence and event timingThat the model or gateway is universally healthy
Both sessions fail on the same routeAuthentication/error body, route capability, client and upstream logsThat the user’s internet connection is the cause
An approved alternate network path succeeds with the same setupThe proxy/intermediary path, certificate handling and connection policyWhich particular proxy rule caused the failure
One authorized provider route fails while another succeedsEach route’s transport and model compatibilityThat a bare HTTPS response confirms WebSocket support
A specific provider error arrives before closureThat error code and its documented recoveryThat increasing the stream timeout will help

Only use network paths and provider accounts you are authorized to test. Keep the model and prompt fixed when possible, and note unavoidable differences. Do not disable TLS verification or remove an organization’s security controls to create a successful test. If you cannot inspect an upstream system, give its operator the redacted incident record instead of guessing at its internal cause.

4. Match the change to the transport, then verify recovery

A WebSocket closure and an SSE idle timeout are different observations. The documented stream_idle_timeout_ms and stream_max_retries settings concern SSE. They are not a general repair for a WebSocket closed by the server. The same reference lists supports_websockets as a custom-provider capability setting; it is not a version-independent switch that repairs every route. Advertising support does not make an incompatible endpoint support that transport.

If your controlled comparison points to a specific route, check that route’s documented transport support and ask its operator to correlate the failure time and request ID. If you find an explicit account, quota or model error, resolve that condition using the matching guide. If only the long original session fails, preserve its work and narrow the next task; do not erase all local state or blindly replay the full sequence.

After one justified change, repeat the short control and then one representative read-only step from the original task. Success means the client reports normal completion and the requested result is present. When you have access to raw response events, check the overall response lifecycle, not only a text fragment ending. For code work, inspect the diff and run the relevant project check before considering the original task recovered. One successful control demonstrates that attempt, not a measured reliability rate.

Download the stream incident worksheet to record the before/after conditions. It contains empty fields, not fabricated successful logs. If the failure persists, preserve those conditions and stop changing unrelated settings; that record is much more useful to a maintainer than “I retried five times.”

Inspect the actual network path

Record the endpoint hostname, proxy configuration, client version and transport. SSE and WebSocket are separate paths; a proxy that handles ordinary HTTPS requests may still have different connection lifetime or WebSocket behavior. Compare logs from the client, gateway and upstream when you control them.

Use an organization-approved standard network path as a comparison if one is available. Do not disable TLS verification or security controls to make a test pass. A certificate error deserves certificate-chain diagnosis, not an insecure bypass.

Check whether failures happen after a consistent period without events, only on a particular route, or only during tool-heavy turns. Those patterns suggest what to test next. They are not sufficient evidence to blame the model provider, the proxy or the client without additional observations.

Understand idle timeout and retry settings

The current Codex configuration reference distinguishes custom-provider stream_idle_timeout_ms, stream_max_retries and request_max_retries. The documented defaults are 300,000 milliseconds, five stream retries and four request retries respectively. These defaults describe the documented settings as of the review date. The stream settings are documented for SSE; do not assume they control every WebSocket failure.

An idle timeout measures inactivity in the relevant stream, not the maximum duration of the entire task. Raising it cannot prevent a server or intermediary from closing a connection for another reason. Change it only when the evidence points to that timeout and your upstream supports the longer wait.

Use the existing config.toml guide to locate the effective configuration. A setting in an unused profile will not change the running session. Avoid copying an unverified switch that claims to disable WebSocket support across every Codex version.

Build a useful incident record

Keep the start and failure times, operating system, client version, transport, endpoint hostname, full error suffix and request or response ID. Add whether a fresh session succeeds, whether tools had already executed, and the shortest harmless task that reproduces the issue.

Remove secrets, cookies, authentication files and private repository contents before sharing logs. Historical issues can provide comparison cases, but check their dates and status. For example, Codex issue 4302 is a closed historical report; it is not evidence that the same old defect remains unfixed today.

Frequently asked questions

Does this error always mean my network failed?

No. The prefix covers an unfinished response path. The full suffix, lifecycle event and provider error are needed to separate connection failures from explicit request failures.

Can I safely ask Codex to repeat everything?

Check what already happened first. File changes and external tool actions may have completed before the stream failed, and repeating them can duplicate work or side effects.

Should I keep increasing the timeout?

Only if the relevant idle timeout is the observed cause. A larger client timeout does not repair invalid credentials, unavailable models, exhausted allowances or upstream connection policies.

Frequently Asked Questions

What does stream disconnected before completion mean?
A Codex response failed to finish as expected. The full error distinguishes an explicit failure from a connection that closed early.
Is response.output_text.done enough to confirm completion?
No. It ends a text portion, not necessarily the complete response lifecycle.
Does a failed stream undo executed tools?
No rollback should be assumed. Inspect the operation state before retrying.