stream disconnected before completion:长任务完成前连接中断怎么处理
LONG-001
stream disconnected before completion严重程度 High一句话结论
一个长时间运行的数据流在任务完成前被切断。最可能是链路上某个环节对长连接设置了最大存活时间或空闲超时;第一步是记录断开前连接维持的时长,看它是否每次都接近同一个数值。
适用环境WindowsmacOSLinuxAndroidiOS
适用客户端通用客户端
最后验证:2026-07-28规则版本:v1内容更新:2026-07-28
结论
这条报错发生在传输层之上的数据流层面:连接曾经正常建立,数据也在流动,但在任务(一次 AI 对话的流式回复、一个大文件下载、一次长轮询推送)自然结束之前,底层连接被某一方切断了。当前证据支持的判断是:问题不在"连不上",而在"保不住"。
适用环境
- Windows / macOS / Linux 桌面客户端
- Android / iOS 移动端
- 所有依赖长时间数据流的应用(流式 API、下载工具、实时推送)
一分钟快速判断
- 立即重试同一个任务。如果每次都能开始传输、又都在相近的时长后断开,几乎可以确定链路上存在固定的存活时间或空闲超时策略。
- 换一个网络(例如从 Wi-Fi 切到手机热点)重跑一次。断开规律消失,说明原网络的 NAT 或防火墙是主要嫌疑。
- 如果断开时长没有规律、且伴随其他应用同时掉线,先检查本地网络稳定性,再考虑线路问题。
这条错误代表什么
“stream disconnected before completion”直译是"数据流在完成前断开"。它不是一个具体的操作系统错误码,而是应用层在发现底层连接(TCP、TLS 或 WebSocket)提前关闭时给出的概括描述。因此它背后可能藏着几种完全不同的底层事件:对端发来 FIN 正常关闭、对端或中间设备发来 RST 强制重置、也可能是本地读超时后主动放弃。仅凭这一条报错无法确定是哪一种,需要下面的证据来区分。
ConnProof 如何判断
运行长连接观察检测:
connproof websocket wss://你的服务地址/path --hold 120000ConnProof 会记录:
- Upgrade 或建连是否成功(排除"连不上"类问题);
- 连接实际保持的毫秒数与请求保持的时长;
- 断开方式:正常关闭帧(含 close code)、FIN 还是 RST;
- 多次运行时保持时长是否稳定。
证据组合的含义:
| 证据 | 更可能的原因 |
|---|---|
| 每次保持时长接近固定值(如 60 秒、300 秒) | 链路上有固定超时策略(NAT、防火墙、网关) |
| 断开方式是 RST | 中间设备强制切断或 NAT 表项过期 |
| 收到正常 close 帧、时长不固定 | 服务端主动回收(负载、发布、闲置策略) |
| 只有无数据传输时才断 | 空闲超时,心跳间隔大于超时阈值 |
最常见原因
- NAT 或防火墙空闲超时:家用路由器和运营商级 NAT 通常在连接静默几十秒到几分钟后清除表项。数据流有间歇(比如 AI 回复之间的停顿)时最容易踩中。
- 中转线路的最大连接存活时间:部分中转服务会无差别断开存活超过固定时长的连接,表现为"每 N 分钟断一次"。
- 服务端回收:服务端重启、发布更新或清理长时间占用资源的连接。断开时间点会集中在特定时刻而不是固定间隔。
- 无线网络切换:笔记本在 Wi-Fi 漫游、手机在基站间切换时底层地址变化,旧连接随之失效。
Windows 排查步骤
- 用
connproof websocket <地址> --hold 120000连续运行三次,记录每次保持时长; - 若时长固定,尝试在应用中缩短心跳(keep-alive)间隔,使其明显小于该时长;
- 检查是否安装了会主动管理连接的安全软件(部分防火墙会限制长连接);
- 换热点复测:规律消失则联系网络管理员或更换路由器的连接超时设置。
macOS 排查步骤
- 同样先做三次保持时长测量;
- 检查系统是否在测试期间进入睡眠——macOS 睡眠会挂起网络栈,唤醒后长连接必然已断;在"电池"设置中排除睡眠干扰后复测;
- 公司网络下若始终固定断开,多为出口防火墙策略,需要网络管理员确认超时配置。
手机端排查步骤
移动系统对后台连接的回收比桌面激进得多:
- Android:确认应用未被电池优化限制后台联网(设置 → 电池 → 不受限制);
- iOS:切到后台超过约 30 秒后连接被挂起属于系统行为,不是链路故障;
- 蜂窝网络下 NAT 超时普遍比宽带短,断开更频繁是正常现象,优先依赖应用自身的断线重连。
如何区分本地问题和节点问题
| 观察 | 指向本地 | 指向节点/线路 |
|---|---|---|
| 换网络后规律消失 | ✓ | |
| 换节点后规律消失 | ✓ | |
| 所有应用同时掉线 | ✓ | |
| 仅走代理的流量断开,直连流量正常 | ✓ | |
| 断开集中在固定时刻(如整点) | ✓(服务端行为) |
心跳间隔应该怎么设
心跳(keep-alive)的作用是在数据流静默期间制造少量流量,让链路上的各级设备相信"这个连接还活着"。设置原则只有一条:心跳间隔必须明显小于链路上最短的空闲超时。实际操作建议:
- 先用上面的保持时长测量估出超时下限。例如三次测量都在 55~65 秒之间断开,说明链路某处的空闲超时约为 60 秒;
- 把心跳间隔设为该值的三分之一到一半(本例即 20~30 秒),留出丢包重试余量;
- 不要盲目设为几秒——过密的心跳在移动网络上会显著耗电,还可能被服务端当作异常流量限制;
- 修改后重新测量,确认保持时长能达到
--hold设定的目标值。
需要注意,心跳只能对抗空闲超时。如果链路存在最大存活时间(无论是否有流量都定时切断),任何心跳设置都无济于事,此时应转向支持断点续传或自动重连的方案,把断开变成可恢复事件。
仍未解决时收集什么信息
只收集脱敏信息:
- ConnProof 错误码(LONG-001)与脱敏报告;
- 客户端名称和版本;
- 操作系统版本;
- 问题发生时间与三次测量的保持时长;
- 失败检测层级(建连成功、保持阶段断开)。
禁止提交:完整订阅链接、密码、验证码、私钥、Token。
重新运行检测
connproof websocket wss://你的服务地址/path --hold 120000 --format markdown --output report.md修复后,保持时长应能达到 --hold 设定值并以"正常关闭"结束。
相关文档
更新记录
- 2026-07-28:规则 v1 发布,完成保持时长证据判定表。