Troubleshooting

How to troubleshoot 502 Bad Gateway and stream disconnected

Locate LLM API's 502 Bad Gateway, stream disconnected, upstream connect error, and read timeouts using short request controls, non-streaming testing, SSE event logging, and hierarchical timeouts.

Updated November 4, 2026Checked 2026-08-26Estimated reading time: 11 minutesApplies to OpenAI Compatible API, SSE streaming output, long context, Agent and reverse proxy
Configuration fields were checked against public documentation. Models, prices, and capabilities can change; verify current values in the console and live API responses.

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.

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:

  1. Do you continue to receive data: event;
  2. Whether ordinary data payloads parse correctly for the protocol. The Chat Completions [DONE] sentinel is not JSON;
  3. Whether the protocol's terminal event arrived, and whether the stop reason indicates truncation, tool calls or an error;
  4. Whether to return an error event before interrupting;
  5. 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:

  1. Pin the client version, Base URL, and model ID, then reuse the same read-only task.
  2. Start with a short non-streaming request to verify authentication, the model, and the base endpoint.
  3. Next, run a streaming request without tools and save the complete SSE event stream.
  4. Finally, run one read-only tool call and verify the incremental tool arguments, finish reason, and returned tool result.
  5. 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 Authorization and Content-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.

FAQ

How do you fix stream disconnected in Codex or Claude Code?

First fix the client version, Base URL, and model, then compare one short non-streaming request with one streaming request using the same key. If only streaming fails, check SSE parsing, proxy buffering, read timeouts, and idle timeouts first; do not retry indefinitely.

Are 502 Bad Gateway and stream disconnected the same problem?

No. A 502 means the gateway did not receive a valid upstream response, while stream disconnected means the streaming connection ended early. If short requests also fail, check authentication, permissions, and the upstream first. If only streaming fails, check the SSE and proxy path.

Why does a basic request succeed while an SSE streaming request fails?

A basic request verifies only the complete response; it does not prove that streaming events, termination markers, or proxy long connections work. Use curl -N to save data events, then check proxy buffering, read timeouts, and the normal termination marker.

Should I retry immediately if the stream closes before a terminal event?

Do not replay it blindly. Preserve the last event, client deadline and request ID, then check whether tools ran and what Link finally billed. Retry only when the request is safe to repeat, with a bounded attempt count. Missing usage does not mean no charge.

Source checked

Reference and Check Sources

Next step

Test the current API before fixing, migrating, or creating a test key

Use a temporary, limited key to inspect model declarations, token fields, SSE, and tool calls. Review current models and pricing only when you need a replacement API.

Model Quality CheckModel PricingCreate Account