502 Bad Gateway 表示作为网关或代理的服务没有从上游获得有效响应。stream disconnected 则说明连接已经开始,但流式响应在完整结束前中断。两者可能相关,但不能只凭错误文字判断是模型、网关、网络还是客户端超时。
如果你搜索的是“Codex stream disconnected 怎么解决”,先做非流式与流式短请求对照:两者都失败,先查 Key、模型权限和上游;只有流式失败,优先查 SSE 事件、代理缓冲、读取超时和长连接空闲超时。
Link SSE 中断:按协议和分组对照
保存 Link 请求的时间、模型 ID、分组、端点和请求 ID,先对同一模型发送短的非流式请求。如果短请求成功而 SSE 失败,再核对客户端事件解析与超时;不要同时换模型、分组和协议后把结果当作单变量实验。
断流后先查看 Link 用量日志再重试长任务。失败响应可能已经产生用量,月卡日额度和钱包余额也可能因重试继续减少;保留失败与重试的两条记录便于核对。
502 或 stream disconnected 先看哪三件事?
先用同一个 Key 和模型发送短请求,对照 stream: false 与 stream: true,并记录请求 ID、最后一个 SSE 事件和中断时间。非流式短请求也失败时,优先检查认证、模型权限和上游状态;只有流式失败时,优先检查 SSE 缓冲、读取超时和代理连接;只有长上下文失败时,优先检查上下文长度、任务总时限和重试策略。
用四组对照快速缩小范围
保持同一个 Key 和模型,只改变一个变量:
| 对照 | A | B | 能说明什么 |
|---|---|---|---|
| 输入长度 | 20 字短问题 | 真实长上下文 | 只在长输入失败,优先查上下文与超时 |
| 流式模式 | stream: false |
stream: true |
只在流式失败,优先查 SSE 和代理缓冲 |
| 客户端 | curl / SDK | Cursor、Dify 或 Agent | 只有客户端失败,查客户端超时和解析 |
| 任务类型 | 普通文本 | 工具调用或多轮 Agent | 只有复杂任务失败,查轮次、工具和总时长 |
每组至少重复 3 次,并记录时间、状态码、请求 ID 与中断位置。一次成功或失败不足以证明长期状态。
看到最后一个事件后,下一步查什么?
先按最终 URL 确定协议,再对照 Chat Completions、Responses 与 Messages 的结束条件。HTTP 200 不排除流内错误;看到结束事件也不代表输出没有截断。
| 观察结果 | 可以判断什么 | 下一步 |
|---|---|---|
| 收到 502 或 HTML,还没建立有效 SSE | 尚未拿到预期事件流,不能据此判断模型身份 | 核对 Content-Type、请求路径、网关响应与请求 ID |
| 有文本,但没有本协议的终止事件 | 结果不完整或未知;不能只看 HTTP 200 | 对齐客户端取消时间、总时限和服务端日志 |
| length、max_tokens 或 response.incomplete | 需要检查输出上限或具体未完成原因,不一定是网络断开 | 保留结束原因,减少任务范围或调整允许的输出额度 |
| 已结束,但 stop_reason 或 finish_reason 指向工具 | 当前模型回合结束,业务任务可能仍在继续 | 验证参数、工具执行结果和回传,不重复执行有副作用操作 |
| 缺少 usage 或账单尚未结算 | 不能据此计算最终费用,更不能推断免费 | 核对 Link 使用日志,把失败与重试记录分开 |
不要在第一次排查时同时换模型、改分组、延长超时和关闭流式。先保存原始条件,按表一次改变一项;任何真实模型请求及重试都可能产生费用。
先跑非流式短请求
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": "只回复 ok"}],
"stream": false
}'
- 短请求也稳定 502:保存请求 ID 和时间,检查平台或上游状态;
- 短请求成功、长请求失败:逐步缩短上下文并增加读取超时;
- 非流式成功、流式失败:进入 SSE 检查;
- curl 成功、应用失败:检查客户端、代理和 SDK 配置。
检查 SSE 流是否完整
使用 -N 禁用 curl 输出缓冲:
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": "分三点解释幂等性"}],
"stream": true
}'
重点观察:
- 是否持续收到
data:事件; - 普通 data 内容能否按协议解析;Chat Completions 的 [DONE] 是结束哨兵,不应直接当 JSON 解析;
- 是否收到本协议终止事件,以及结束原因是否为截断、工具调用或错误;
- 中断前是否返回错误事件;
- 反向代理是否缓冲或压缩了流。
更完整的客户端示例和代理检查见 流式输出与 SSE 接入教程。
以上 curl 示例仅针对 Chat Completions。不能用它的成功证明 Codex 的 Responses 或 Claude Code 的 Messages 正常。--max-time 120 是客户端总时限;出现 curl 超时,应先记录是否恰好达到该时限,而不是直接归因于上游。
把超时拆成三层
不要只设置一个笼统的 timeout=30:
| 超时 | 作用 | 常见误配 |
|---|---|---|
| 连接超时 | 建立 TCP/TLS 连接 | 设置过长,网络故障迟迟不失败 |
| 读取超时 | 等待下一个响应分片 | 设置过短,推理或工具阶段被误杀 |
| 任务总时限 | 限制完整业务任务 | 没有上限,Agent 可以无限运行 |
长推理和工具调用可能在两个文本分片之间等待更久,但这不意味着总时限应该无限增加。应分别设置合理的读取超时与业务截止时间。
Codex 或 Claude Code 报 stream disconnected
Codex 和 Claude Code 的长任务不只依赖普通文本流,还可能包含工具参数增量、工具结果回传、上下文压缩和连续会话。短聊天成功,不能证明 Agent 链路完整。
按下面顺序复测:
- 固定客户端版本、Base URL、模型 ID 和同一个只读任务。
- 先用非流式短请求确认认证、模型和基础路径正常。
- 再执行一次不调用工具的流式请求,保存完整 SSE 事件。
- 最后执行单次只读工具调用,检查参数增量、结束原因和工具结果是否完整。
- 如果只在上下文压缩后中断,保存中断前最后一个事件、会话长度和客户端日志,不要只提高超时。
Codex 还需要单独核对 Responses API 和连续响应事件;Claude Code 需要核对 Anthropic Messages 兼容入口。对应检查表见 Codex 网关检查清单 和 Claude Code 网关检查清单。
反向代理重点检查
如果应用前还有 Nginx、Cloudflare、Lucky 或其他代理,核对:
- 是否关闭了不适合 SSE 的响应缓冲;
- 上游读取超时是否短于客户端;
- 是否完整转发
Authorization和Content-Type; - 响应是否被错误压缩、拼接或缓存;
- 长连接是否被空闲超时提前关闭;
- 请求体大小限制是否小于真实上下文。
不要一开始就同时放大所有超时和请求体限制。先通过短请求、长请求和流式对照确认是哪一层触发。
502 应该怎么重试
只对可以安全重复的请求做有限重试,并加入抖动。以下情况要特别谨慎:
- 生图、视频等异步任务可能已经创建成功;
- 工具调用可能已经写入数据库或发送消息;
- 流式请求中断前已经向用户输出部分内容;
- 服务端已扣费但客户端没有收到完整响应。
对有副作用的任务,应使用幂等键、任务 ID 或业务去重机制。无法判断服务端是否执行时,不要直接重新发起。
修复完成的验收标准
- 短请求、真实上下文分别完成多次验证;
- 非流式与流式均能正常结束;
- 日志保留请求 ID、中断时间、首个分片和最后一个分片时间;
- 连接、读取和任务总时限职责清楚;
- 代理不会缓冲 SSE 或提前关闭长连接;
- 重试次数有限,有副作用任务具备去重机制。
如果同一入口持续出现异常,可以先运行 模型质量检测 保存协议与行为报告,再按 API 对比测试模板 从相同地区、模型和题集复测。检测报告用于定位兼容性问题,不等同于厂商身份认证或长期 SLA。
匿名排查案例:等待首包后出现 client_gone
2026-10-11 核对的两笔 Link 流式请求分别持续约 91 秒和 94 秒,均未收到有效数据。Tunnel 先记录 Incoming request ended abruptly: context canceled,应用随后记录 client_gone 并关闭上游响应。关闭之后出现的 http2: response body closed 不能单独当作上游先故障的证据。
这两笔发生时,源站没有重启;已核对的扫描超时和代理响应头超时均为 300 秒。因此不能把约 90 秒的中止归到这些 300 秒超时分支。对照中也观察到同一路由首个有效响应等待偏长,但样本不足以承诺换路由一定解决。
能够确认的是下游请求上下文已取消,不能仅从源站日志继续区分用户点了停止、客户端超时、用户网络中断还是边缘链路取消。排查应补客户端截止时间和断开时间,再与同一请求的代理记录对齐;不要先无限延长超时或自动重试长任务。
账务复核显示,这两笔预扣均已释放,最终消耗为 0。这个结果只适用于这两个样本;其他中断请求如果已产生有效用量,必须分别核对最终结算,不能推出所有 client_gone 都免费。
本案例是诊断记录,没有发布“网络已根治”的结论,也没有公开账号、请求 ID、IP、渠道凭据或用户输入。修复是否有效,应再用同一客户端和模型完成短请求、完整 SSE 结束与一次只读工具调用的对照。