Claude Code 在 Windows 上流式返回 ECONNRESET:中转 API 兼容性排查清单
Claude Code 在 Windows 上出现“首块已到、随后 ECONNRESET”时,先区分客户端、代理传输和上游故障。本文给出日志判断、SSE/分块响应核验、临时绕行与更换中转渠道的检查顺序。
正文
如果 Claude Code 能发出请求、日志里也出现了第一段响应,随后却报:
API Error: Connection closed mid-response
ECONNRESET
不要立刻把它归因于 API Key、模型不存在或中转站余额不足。这个症状更具体:请求大概率已经通过认证并开始返回,故障发生在流式响应的中途。在 Windows 原生客户端、HTTP 代理或 Anthropic 兼容中转 API 的组合里,响应格式、传输编码和客户端运行时都可能影响结果。
本文针对的是“首块响应已经到达,之后连接被重置或被客户端判定为不完整”的场景,重点回答四个问题:
- 怎么判断是认证问题、上游过载,还是流式传输问题?
- 为什么
claude -p偶尔能成功,却不代表流式链路正常? - 中转站或代理侧应该检查哪些 HTTP/SSE 细节?
- 什么时候该换渠道,什么时候应该先升级 Claude Code 或做本地绕行?
资料范围:本文资料与公开问题核验于 2026 年 8 月 29 日。GitHub 问题中的复现来自社区报告,不等同于 Anthropic 已确认的官方根因;文中将“已观察到的现象”“协议要求”和“排查建议”分开说明。
先看懂这个错误:首块到达意味着什么
一次典型的 Claude Code 流式请求,大致会经历:
- 客户端向配置的
ANTHROPIC_BASE_URL发起/v1/messages请求。 - 中转服务或上游完成认证、模型选择与请求校验。
- 服务端返回
text/event-stream响应。 - 客户端收到
message_start、内容块增量等事件。 - 服务端以
message_stop收尾,连接正常结束。
Anthropic 的 Messages 流式文档将这类响应定义为带事件名的 Server-Sent Events(SSE),事件序列中包括 message_start、内容块事件和 message_stop。因此,日志中出现“Stream started”或“first chunk”后再出现 ECONNRESET,和“请求一开始就被 401 拒绝”不是同一层问题。
但这也不能证明上游一定没问题。服务端可能在输出首块后崩溃、超时、主动断开,或者中转层在转发过程中破坏了响应边界。需要把客户端日志、代理响应头、上游请求结果放在一起看。
先做分类:四种容易混淆的故障
| 表现 | 更应该先查什么 | 是否优先更换中转站 |
|---|---|---|
| 请求一开始就是 401/403 | Key、认证头、账号权限、接口路径 | 否,先修配置 |
| 429 或 529,尚未收到正文 | 限流、加速限制、上游过载、额度 | 视持续时间和多站对照结果决定 |
| 首块到达后连接重置 | SSE 转发、HTTP 版本、代理、客户端运行时、上游中途断开 | 先做传输对照,再决定 |
| 请求成功但只是不流式、等待很久 | 非流式回退、网关缓冲、响应超时 | 需要检查渠道是否真正支持流式 |
Anthropic 的错误文档把 401、403、429、500、504、529 分别对应到认证、权限、限流/加速限制、服务端错误、超时和过载等类别;ECONNRESET 则是客户端网络栈报告的连接被重置,不能直接当成某个 HTTP 状态码使用。
一个实用判断是:
- 401/403:不要浪费时间调 SSE,先确认
ANTHROPIC_AUTH_TOKEN、Key 权限和 base URL。 - 429/529:记录响应状态、
request-id和retry-after(如果有),再看多个时间点是否持续。 - 首块后 ECONNRESET:优先检查流式链路,不要只重复充值或反复生成 Key。
- 最终成功但耗时异常:确认客户端是否重试多次后自动改用非流式请求。成功结果不代表首选流式通道可用。
一个公开复现把问题缩小到了“流式响应路径”
2026 年 8 月 5 日,Claude Code GitHub issue #84072 报告了 Windows 10/11 上的类似症状:请求可以到达 API,第一字节/第一块响应也能收到,随后出现 ECONNRESET,客户端反复重试。报告还记录了在干净目录、不同网络和安全模式下的对照结果,说明至少有一类问题并不像 MCP、插件或项目提示词导致的普通配置错误。
随后,2026 年 8 月 6 日公开的 issue #84442 把场景描述得更具体:Claude Code Windows 原生版本 2.1.221–2.1.223 通过本地明文 HTTP/1.1 代理接收 Transfer-Encoding: chunked 的流式响应时失败,而同一路径的非流式响应可以成功;把响应改为 EOF 结束、移除分块传输后,报告者观察到绕行成功。该问题页仍是社区问题报告,不能视为已由官方确认的普遍回归,也不能推断所有中转站都会触发。
这两条报告给出的共同排查方向是:同一个模型、同一个 Key、同一台机器,分别比较直连、代理、中转、流式和非流式;不要只看最后有没有得到文本。
第一步:确认 Claude Code 实际发往哪里
Claude Code 官方 LLM Gateway 文档说明,ANTHROPIC_BASE_URL 用来指定网关地址;同时只设置 base URL 并不会自动替换已有的订阅凭据。网关凭据是否生效,会影响实际计费主体、权限和上游路径。
在 Windows PowerShell 中先查看当前会话变量:
$env:ANTHROPIC_BASE_URL
$env:ANTHROPIC_AUTH_TOKEN
$env:ANTHROPIC_API_KEY
$env:HTTP_PROXY
$env:HTTPS_PROXY
重点核对:
ANTHROPIC_BASE_URL是否重复拼接了/v1。不同中转站文档可能要求根地址或/v1,不要凭经验叠加。- 是否同时设置了
ANTHROPIC_AUTH_TOKEN和ANTHROPIC_API_KEY,导致实际使用的凭据与预期不同。 - 是否存在全局
HTTP_PROXY/HTTPS_PROXY,让 Claude Code 走了另一条链路。 - 终端、VS Code 扩展、桌面端是否继承了不同的环境变量。
- 中转站文档要求的是 Anthropic 原生协议,还是 OpenAI 兼容协议转换;Claude Code 的
/v1/messages不能仅凭“支持 Claude”四个字判断兼容。
排查时不要把完整 API Key 粘贴到工单、截图或命令输出中。若怀疑 Key 已经泄露,应在渠道控制台撤销并重新生成。
第二步:用最小请求区分认证与流式问题
先做一个尽量短的请求,减少长上下文、工具调用和复杂模型推理对结果的影响。以下示例使用 Anthropic Messages API 的基本字段;BASE_URL 和 KEY 请替换成当前渠道的配置,不要把密钥写入脚本仓库。
$headers = @{
"x-api-key" = $env:ANTHROPIC_AUTH_TOKEN
"anthropic-version" = "2023-06-01"
"content-type" = "application/json"
}
$body = @{
model = "你的渠道文档中列出的模型名"
max_tokens = 32
stream = $false
messages = @(
@{ role = "user"; content = "只回复 OK" }
)
} | ConvertTo-Json -Depth 6
Invoke-WebRequest `
-Uri "$env:ANTHROPIC_BASE_URL/messages" `
-Method Post `
-Headers $headers `
-Body $body
这个请求的目的不是测性能,而是回答:
- 是否能通过认证?
- 模型名是否被渠道接受?
- 响应是否能完整返回?
- HTTP 状态与错误体是什么?
然后只把 stream 改成 $true,观察响应头和事件流。如果非流式稳定成功、流式在首块后断开,问题范围就从“所有 API 调用失败”缩小为“流式传输/代理/客户端兼容”。
不同渠道可能要求额外的认证头、不同的模型别名或不同的 base URL。这里的命令只能作为诊断模板,不能替代渠道自己的接入文档。
第三步:中转或代理必须正确转发 SSE
Anthropic 官方流式文档要求客户端按 SSE 事件消费响应,而不是把整段正文当成一次普通 JSON。中转层至少应核验以下项目:
响应头
Content-Type: text/event-stream
Cache-Control: no-cache
如果代理使用 HTTP/1.1 分块传输,还应正确处理 Transfer-Encoding: chunked;不能同时发送相互冲突的 Content-Length。不要把 hop-by-hop 的传输头原样跨连接复制到不适用的协议层。
MDN 对 Transfer-Encoding: chunked 的说明是:响应体被拆成带长度的块,以十六进制长度开头,最后用零长度块结束;Content-Length 应省略。MDN 同时提醒,HTTP/2 不使用这一 HTTP/1.1 传输头。也就是说,“SSE 事件格式正确”与“HTTP 传输分帧正确”是两个检查项。
正文事件
转发器不应:
- 把多个 SSE 事件拼成一段不带分隔的 JSON;
- 删除事件之间必要的空行;
- 把
data:内容重新序列化后丢失换行或 Unicode; - 在收到首块后等待完整上游响应,再一次性返回;
- 因为心跳、工具调用或思考阶段出现空闲,就错误关闭连接;
- 把上游
message_stop之前的中断伪装成成功的完整响应。
Cloudflare Workers 的 Streams 文档也明确区分了流式响应与缓冲:要保持边到边的流式行为,应使用 ReadableStream 等 Streams API 处理响应体,并通过 Response 直接返回流。这个原则同样适用于 Node、Nginx、Caddy、API 代理和中转服务:读取、改写、转发时不能无意中把流变成缓冲响应。
客户端与代理的组合
公开 issue #84442 的报告显示,某些 Windows 原生版本对本地明文 HTTP/1.1 代理的分块流式响应更敏感,而 HTTPS 直连或非分块响应在该报告的对照实验中表现不同。这个结果不能直接推出“chunked 一定有问题”,但足以让它成为中转渠道验收时的 A/B 项:
| A/B 变量 | 需要记录 |
|---|---|
| 直连 vs. 代理 | ANTHROPIC_BASE_URL、代理变量、代理是否终止 TLS |
| HTTPS vs. HTTP | 客户端到第一跳的协议 |
| chunked vs. 非 chunked | Transfer-Encoding、Content-Length、连接关闭方式 |
| stream=false vs. stream=true | 是否首块后断开、是否完整出现 message_stop |
| Claude Code 版本 | 原生安装、npm 安装、具体版本号 |
| 目标模型 | 模型名、上下文大小、是否启用长上下文/工具 |
第四步:判断是“站点问题”还是“客户端/链路问题”
不要用一次失败就给中转站下结论。建议按下面的顺序做最小对照:
1. 同一渠道,非流式与流式对照
- 非流式失败:优先查 Key、模型名、余额、权限或接口路径。
- 非流式成功、流式失败:优先查响应头、SSE 事件、网关缓冲和连接保持。
2. 同一渠道,Claude Code 与 curl/Node 对照
如果 curl 或 Node 能完整读取同一流,而 Claude Code 不能,客户端运行时或客户端与代理的组合值得优先怀疑。反过来,如果所有客户端都在同一位置断开,才更像渠道、上游或网络路径问题。
3. 同一客户端,两个渠道对照
选择两个都明确支持 Anthropic 原生 Messages 流式协议的渠道,使用相同的短提示、相近的模型和相同时间窗口。记录:
- HTTP 状态;
- 首字节时间;
- 是否收到完整结束事件;
- 是否出现重试;
- 连接断开前收到多少内容;
- 渠道是否返回 request ID。
这不是长期稳定性评测,样本太小不能产生“稳定/不稳定”的绝对结论;它只是帮助定位当前兼容性。
4. 关闭非必要功能再测
先暂时关闭 MCP、插件、hooks、复杂工具调用和超长上下文,用“只回复 OK”测试。这样做不是因为 MCP 必然导致 ECONNRESET,而是为了减少请求体和事件类型,让 A/B 结果更容易解释。
第五步:几个可执行的绕行方案
方案 A:升级或回退 Claude Code,并保留版本记录
公开问题涉及具体 Windows 原生版本,因此第一步是记录当前版本,再查看官方 release notes 是否有修复或回归说明。不要在没有记录旧版本和新版本的情况下连续升级,否则无法知道哪个版本改变了结果。
可以记录:
claude --version
claude doctor
如果升级后问题消失,也只能说明“该版本组合下复现不再出现”,不能据此证明某个中转站长期可靠。
方案 B:先用非流式请求确认业务可用性
如果业务允许等待完整响应,可临时把测试请求改成 stream: false,用于验证 Key、模型和额度。但这不是流式兼容问题的最终修复:非流式可能增加等待时间,也可能触发代理或客户端的响应超时。
方案 C:让一个受控桥接层重新组织响应
issue #84442 报告了通过本地桥接层去除分块传输、让响应以连接关闭作为结束的绕行方式。这个方法的适用前提是:你理解桥接层会接触模型请求和响应,并且能控制其安全、日志、超时和凭据配置。
不建议为了“能跑”直接把 API Key 写进临时脚本,或在桥接层记录完整提示词。若采用桥接层,至少做到:
- 监听本机回环地址,而不是暴露到公网;
- API Key 放环境变量或系统密钥存储;
- 默认关闭完整请求/响应日志;
- 明确连接超时、上游超时和客户端取消的行为;
- 保留
request-id、HTTP 状态和错误类型等必要诊断信息; - 只在确认响应完整结束后再把“成功”记账。
方案 D:换一个明确支持 Anthropic 原生流式协议的渠道
当你确认:
- 同一个 Claude Code 版本在另一个渠道流式正常;
- 当前渠道非流式正常但流式持续失败;
- 代理响应头或 SSE 事件存在不一致;
- 渠道无法说明
/v1/messages、SSE、工具调用和结束事件的实现;
这时更换渠道是合理的排障动作,但不要只看宣传页上的“支持 Claude”。在 RouterHub 的平台目录中,可以先按 Claude Code / Anthropic 接入场景筛选,再回到具体站点核对模型名、协议、额度、价格和当前限制。目录信息是发现候选的入口,最终仍应以你实际访问时的渠道文档和小额测试为准。
选中转 API 时,流式兼容性应该问什么
在注册或充值前,建议把问题问具体:
- 是否支持 Anthropic 原生
/v1/messages,还是只支持 OpenAI 兼容接口? stream: true是否经过真实端到端测试?测试的 Claude Code 版本和 Windows 环境是什么?- 响应是否保留 SSE 事件名、
data:行和message_stop? - 是否存在响应缓冲、最大流式时长、空闲超时或首块超时?
- 使用 HTTP/1.1 代理时,
Transfer-Encoding与Content-Length如何处理? - 工具调用、思考内容、长上下文和取消请求是否有额外限制?
- 失败请求如何区分上游 529、渠道限流、余额不足和客户端断开?
- 是否能提供 request ID,方便定位某一次请求?
如果对方只能回答“支持 Claude”或“能跑 Claude Code”,但不能回答协议和错误边界,建议先做低成本验证,不要把长期项目直接迁移过去。
一份最小记录模板
每次 A/B 测试都保存下面的信息,后续换渠道或升级客户端时才有可比性:
日期(UTC):2026-08-29
操作系统:Windows 10/11
Claude Code 版本:
安装方式:native / npm
BASE_URL(隐藏域名后的完整路径):
模型名:
请求:短提示;max_tokens;是否 stream
代理:无 / HTTP / HTTPS / 本地桥接
HTTP 状态:
响应头:Content-Type / Transfer-Encoding / Content-Length
首字节时间:
是否收到 message_stop:
错误:401 / 429 / 529 / ECONNRESET / timeout / 其他
request-id:
是否重试或回退到非流式:
这份记录比“今天这个站不稳定”更有价值,因为它能把客户端版本、渠道实现、传输协议和上游状态分开。
结论:先证明是哪一跳断了,再决定要不要换站
Windows 上 Claude Code 的“首块已到、随后 ECONNRESET”值得单独看待。它可能来自客户端原生运行时与某种 HTTP 流式响应的组合,也可能是中转层缓冲、分块边界、空闲超时或上游中途断开。公开 issue 提供了有价值的复现线索,但没有替你完成环境诊断。
最省时间的顺序是:
- 记录 Claude Code 版本和实际环境变量;
- 用最小请求分别测试非流式和流式;
- 检查
Content-Type、SSE 事件、Transfer-Encoding和结束事件; - 用 curl/Node 与另一个渠道做 A/B;
- 再选择升级、桥接、暂时非流式或更换中转站。
这样做的好处是,即使最终需要换渠道,你也能知道是在换一个真正的兼容性问题,还是在重复支付一个本来属于客户端或代理的故障。
参考来源
- Anthropic Claude Code:LLM Gateway 与
ANTHROPIC_BASE_URL配置说明(官方文档)
https://docs.anthropic.com/en/docs/claude-code/llm-gateway - Anthropic API:Errors,关于 401、403、429、504、529 与 SDK 重试的说明(官方文档)
https://platform.claude.com/docs/en/api/errors - Anthropic API:Streaming Messages,SSE 事件与
message_stop(官方文档)
https://platform.claude.com/docs/en/build-with-claude/streaming - Claude Code GitHub issue #84072:Windows 首块响应后
ECONNRESET的社区复现报告
https://github.com/anthropics/claude-code/issues/84072 - Claude Code GitHub issue #84442:Windows 原生版本通过明文 HTTP/1.1 分块代理流式失败的社区复现报告
https://github.com/anthropics/claude-code/issues/84442 - Cloudflare Workers Streams:使用
ReadableStream保持响应流式传输(官方工程文档)
https://developers.cloudflare.com/workers/runtime-apis/streams/ - MDN:
Transfer-Encoding与 HTTP/1.1 chunked 编码说明
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Transfer-Encoding
动态资料核验日期:2026 年 8 月 29 日(UTC)。GitHub issue 属于公开社区报告;Anthropic 与 Cloudflare 文档用于核对协议、配置和错误语义,不表示它们已确认本文所述具体组合的根因。
相关阅读
- AI API 平台目录:按模型和预算横向比较各站价格与支持情况
- claudeapi 详情:注册入口、模型覆盖和使用限制