502 Bad Gateway Indicates that the service acting as a gateway or proxy is not getting a valid response from the upstream.stream disconnected It means that the connection has started, but the streaming response was interrupted before it was completely completed. The two may be related, but you cannot determine whether it is a model, gateway, network, or client timeout based on the error text alone.
If you are searching for how to fix Codex stream disconnected, compare short non-streaming and streaming requests first. If both fail, check the key, model permissions, and upstream. If only streaming fails, check SSE events, proxy buffering, read timeouts, and long-connection idle timeouts first.
What three things should I check first for a 502 or stream disconnected error?
Using the same key and model, send a short request and compare stream: false with stream: true, then record the request ID, the final SSE event, and the disconnect time. If a short non-streaming request also fails, check authentication, model access, and upstream status first. If only streaming fails, check SSE buffering, read timeouts, and proxy connections. If only long contexts fail, check context length, the overall task deadline, and the retry policy.
Use four sets of controls to quickly narrow down the scope
Keep the same Key and model, and only change one variable:
| control | A | B | What can be explained |
|---|---|---|---|
| Enter length | 20 word short question | real long context | Only when long input fails, the context and timeout will be checked first. |
| streaming mode | stream: false |
stream: true |
Only when streaming fails, check SSE and proxy buffering first. |
| client | curl / SDK | Cursor, Dify or Agent | Only the client fails, check client timeout and resolution |
| Task type | normal text | Tool call or multiple rounds of Agent | Only complex tasks failed, check the rounds, tools and total time |
Repeat each group at least 3 times, and record the time, status code, request ID and interruption location. One success or failure is not enough to prove long-term status.
Run non-streaming short requests first
curl -i https://www.aifast.link/v1/chat/completions \
-H "Authorization: Bearer $AIFAST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Model copied from consoleID",
"messages": [{"role": "user", "content": "Reply with only ok"}],
"stream": false
}'
- Short requests are also stable 502: save the request ID and time, check the platform or upstream status;
- Short requests succeed and long requests fail: gradually shorten the context and increase the read timeout;
- Non-streaming success, streaming failure: enter SSE check;
- curl succeeds, application fails: check client, proxy and SDK configuration.
Check if SSE flow is complete
Use -N Disable curl output buffering:
curl -N https://www.aifast.link/v1/chat/completions \
-H "Authorization: Bearer $AIFAST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Model copied from consoleID",
"messages": [{"role": "user", "content": "Explain idempotence in three points"}],
"stream": true
}'
Key observations:
- Do you continue to receive
data:event; - Whether each event is client-parsable JSON;
- Whether a normal end tag appears;
- Whether to return an error event before interrupting;
- Whether the reverse proxy buffered or compressed the stream.
For a more complete client example and proxy check seeStreaming output and SSE access tutorial.
Split timeouts into three layers
Don’t just set a general timeout=30:
| timeout | function | Common mismatches |
|---|---|---|
| Connection timeout | Establish a TCP/TLS connection | The setting is too long, and the network failure continues to fail. |
| Read timeout | Wait for the next response fragment | The setting is too short and the inference or tool phase is accidentally killed. |
| total task time | Limit complete business tasks | There is no upper limit, the Agent can run indefinitely |
Long inferences and tool calls may wait longer between two text shards, but this does not mean that the total time limit should increase indefinitely. Reasonable read timeout and business deadline should be set respectively.
Codex or Claude Code reports stream disconnected
Long-running Codex and Claude Code tasks involve more than plain text streaming. They may depend on incremental tool arguments, tool-result round trips, context compaction, and session continuity. A successful short chat does not prove the complete agent workflow.
Retest in the following order:
- Pin the client version, Base URL, and model ID, then reuse the same read-only task.
- Start with a short non-streaming request to verify authentication, the model, and the base endpoint.
- Next, run a streaming request without tools and save the complete SSE event stream.
- Finally, run one read-only tool call and verify the incremental tool arguments, finish reason, and returned tool result.
- If the stream disconnects only after context compaction, save the last event received, the session length, and the client logs instead of only increasing the timeout.
For Codex, also verify the Responses API and its streaming events. For Claude Code, verify the Anthropic Messages compatibility endpoint. See the corresponding checklists Codex Gateway Checklist and Claude Code Gateway Checklist.
Reverse proxy key checks
If there is Nginx, Cloudflare, Lucky or other proxies in front of the application, check:
- Whether response buffering inappropriate for SSE is turned off;
- Whether the upstream read timeout is shorter than the client;
- Whether to forward completely
AuthorizationandContent-Type; - Whether the response was incorrectly compressed, spliced, or cached;
- Whether the long connection is closed early due to idle timeout;
- Whether the request body size limit is smaller than the real context.
Don't start by enlarging all timeouts and request body limits at the same time. First, confirm which layer is triggered by short request, long request and streaming comparison.
502 How to retry
Only do limited retries for requests that can be safely repeated, and add jitter. Be especially cautious in the following situations:
- Asynchronous tasks such as drawing pictures and videos may have been created successfully;
- Tool calls may have written to the database or sent messages;
- Part of the content has been output to the user before the streaming request is interrupted;
- The server has deducted the fee but the client has not received a complete response.
For tasks with side effects, idempotent keys, task IDs, or business deduplication mechanisms should be used. When you cannot determine whether the server is executing, do not reinitiate it directly.
Acceptance criteria for repair completion
- Short requests and real contexts have been verified multiple times respectively;
- Both non-streaming and streaming can end normally;
- The log retains the request ID, interruption time, first fragment and last fragment time;
- Responsibilities for connection, reading and total task time limit are clear;
- The proxy does not buffer SSE or close long connections early;
- The number of retries is limited, and tasks with side effects have a deduplication mechanism.
If exceptions continue to occur at the same entry, you can runModel Quality CheckSave the agreement and behavior report, then clickAPI comparison test templateRetest from the same region, model, and question set. Test reports are used to locate compatibility issues and are not equivalent to vendor identity certification or long-term SLA.