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.
Link SSE disconnects: compare protocol and group
Record the time, model ID, group, endpoint and request ID of the Link request, then send a short non-streaming request to the same model. If only SSE fails, check event parsing and timeouts. Changing the model, group and protocol together is not a controlled comparison.
Check Link usage logs before retrying a long disconnected task. A failed response may already have incurred usage, and retries may consume plan or wallet allowance. Keep both failed and retried request records for comparison.
Review Link funding and monthly-plan rules
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 | If only the client fails, check client timeouts and SSE parsing |
| 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.
What should you check after the last event?
Identify the protocol from the final URL, then consult the completion criteria for Chat Completions, Responses and Messages. HTTP 200 does not rule out an error inside the stream, and a terminal event does not rule out truncated output.
| Observed result | What it establishes | Next step |
|---|---|---|
| 502 or HTML arrives before a valid SSE stream | The expected event stream has not been established; this does not identify the model | Check Content-Type, request path, gateway response and request ID |
| Text arrives without the protocol's terminal event | The result is incomplete or unknown; HTTP 200 alone is insufficient | Correlate client cancellation, the overall deadline and server logs |
| length, max_tokens or response.incomplete | Inspect the output limit or specific incomplete reason; it may not be a network disconnection | Save the stop reason, narrow the task or adjust the allowed output budget |
| The turn ends with a tool-related stop_reason or finish_reason | The model turn has ended, but the business task may still be in progress | Validate arguments, tool results and their return; do not repeat side effects |
| Usage is missing or billing has not settled | Final cost is unknown; do not assume the request was free | Check Link usage logs and keep failed requests separate from retries |
Do not change the model, group, timeout and streaming mode together during the first investigation. Record the initial conditions and change one variable at a time. Real model requests and retries may incur charges.
Run non-streaming short requests first
curl -i --connect-timeout 10 --max-time 120 https://www.aifast.link/v1/chat/completions \
-H "Authorization: Bearer ${AIFAST_API_KEY:?Set AIFAST_API_KEY locally before running}" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_ID",
"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 --include --connect-timeout 10 --max-time 120 https://www.aifast.link/v1/chat/completions \
-H "Authorization: Bearer ${AIFAST_API_KEY:?Set AIFAST_API_KEY locally before running}" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_MODEL_ID",
"messages": [{"role": "user", "content": "Explain idempotence in three points"}],
"stream": true
}'
Key observations:
- Do you continue to receive
data:event; - Whether ordinary data payloads parse correctly for the protocol. The Chat Completions [DONE] sentinel is not JSON;
- Whether the protocol's terminal event arrived, and whether the stop reason indicates truncation, tool calls or an error;
- Whether to return an error event before interrupting;
- Whether the reverse proxy buffered or compressed the stream.
For a fuller client example and proxy checklist, see Streaming output and SSE access tutorial.
These curl examples only test Chat Completions. Their success does not establish that Codex Responses or Claude Code Messages work. --max-time 120 is the client's overall deadline. When curl times out, check whether that deadline was reached before blaming the upstream service.
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 the same endpoint keeps failing, run Model Quality Check to save a protocol and behavior report, then follow API comparison test template to retest from the same region with the same model and question set. Reports help diagnose compatibility; they do not certify the provider's identity or establish a long-term SLA.
An anonymized investigation: client_gone while waiting for the first event
Two Link streaming requests examined on 11 October 2026 lasted about 91 and 94 seconds, with no valid data received. The Tunnel recorded Incoming request ended abruptly: context canceled before the application recorded client_gone and closed the upstream response. A subsequent http2: response body closed message is not, by itself, evidence that the upstream failed first.
The origin did not restart during those requests. The checked scanner and proxy response-header timeouts were both 300 seconds, so the roughly 90-second cancellations cannot be attributed to those 300-second timeout branches. Other samples showed a long wait for the first valid response on the same route, but the sample is insufficient to promise that changing routes will solve it.
The confirmed observation is cancellation of the downstream request context. Origin logs alone cannot distinguish a user pressing Stop, a client timeout, a user-network failure or an edge cancellation. Compare the client deadline and disconnect time with proxy records for the same request before extending timeouts or retrying long tasks.
Billing checks showed that both reservations were released and both final charges were zero. This result applies only to these two samples. Interrupted requests that produced valid usage require individual settlement checks; client_gone does not imply that every request is free.
This is a diagnostic case, not a claim that the network issue was permanently fixed. Account details, request IDs, IPs, channel credentials and user input are omitted. Validate any subsequent fix with the same client and model using a short request, a complete SSE ending and one read-only tool call.