RH
RouterHub AI API 中转站导航与平台推荐
博客

Claude Code 在 Windows 上流式返回 ECONNRESET:中转 API 兼容性排查清单

Claude Code 在 Windows 上出现“首块已到、随后 ECONNRESET”时,先区分客户端、代理传输和上游故障。本文给出日志判断、SSE/分块响应核验、临时绕行与更换中转渠道的检查顺序。

muchacha 2026-08-29 02:24:46

正文

如果 Claude Code 能发出请求、日志里也出现了第一段响应,随后却报:

API Error: Connection closed mid-response
ECONNRESET

不要立刻把它归因于 API Key、模型不存在或中转站余额不足。这个症状更具体:请求大概率已经通过认证并开始返回,故障发生在流式响应的中途。在 Windows 原生客户端、HTTP 代理或 Anthropic 兼容中转 API 的组合里,响应格式、传输编码和客户端运行时都可能影响结果。

本文针对的是“首块响应已经到达,之后连接被重置或被客户端判定为不完整”的场景,重点回答四个问题:

  1. 怎么判断是认证问题、上游过载,还是流式传输问题?
  2. 为什么 claude -p 偶尔能成功,却不代表流式链路正常?
  3. 中转站或代理侧应该检查哪些 HTTP/SSE 细节?
  4. 什么时候该换渠道,什么时候应该先升级 Claude Code 或做本地绕行?

资料范围:本文资料与公开问题核验于 2026 年 8 月 29 日。GitHub 问题中的复现来自社区报告,不等同于 Anthropic 已确认的官方根因;文中将“已观察到的现象”“协议要求”和“排查建议”分开说明。

先看懂这个错误:首块到达意味着什么

一次典型的 Claude Code 流式请求,大致会经历:

  1. 客户端向配置的 ANTHROPIC_BASE_URL 发起 /v1/messages 请求。
  2. 中转服务或上游完成认证、模型选择与请求校验。
  3. 服务端返回 text/event-stream 响应。
  4. 客户端收到 message_start、内容块增量等事件。
  5. 服务端以 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 时,流式兼容性应该问什么

在注册或充值前,建议把问题问具体:

  1. 是否支持 Anthropic 原生 /v1/messages,还是只支持 OpenAI 兼容接口?
  2. stream: true 是否经过真实端到端测试?测试的 Claude Code 版本和 Windows 环境是什么?
  3. 响应是否保留 SSE 事件名、data: 行和 message_stop?
  4. 是否存在响应缓冲、最大流式时长、空闲超时或首块超时?
  5. 使用 HTTP/1.1 代理时,Transfer-Encoding 与 Content-Length 如何处理?
  6. 工具调用、思考内容、长上下文和取消请求是否有额外限制?
  7. 失败请求如何区分上游 529、渠道限流、余额不足和客户端断开?
  8. 是否能提供 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 提供了有价值的复现线索,但没有替你完成环境诊断。

最省时间的顺序是:

  1. 记录 Claude Code 版本和实际环境变量;
  2. 用最小请求分别测试非流式和流式;
  3. 检查 Content-Type、SSE 事件、Transfer-Encoding 和结束事件;
  4. 用 curl/Node 与另一个渠道做 A/B;
  5. 再选择升级、桥接、暂时非流式或更换中转站。

这样做的好处是,即使最终需要换渠道,你也能知道是在换一个真正的兼容性问题,还是在重复支付一个本来属于客户端或代理的故障。

参考来源

  1. Anthropic Claude Code:LLM Gateway 与 ANTHROPIC_BASE_URL 配置说明(官方文档)
    https://docs.anthropic.com/en/docs/claude-code/llm-gateway
  2. Anthropic API:Errors,关于 401、403、429、504、529 与 SDK 重试的说明(官方文档)
    https://platform.claude.com/docs/en/api/errors
  3. Anthropic API:Streaming Messages,SSE 事件与 message_stop(官方文档)
    https://platform.claude.com/docs/en/build-with-claude/streaming
  4. Claude Code GitHub issue #84072:Windows 首块响应后 ECONNRESET 的社区复现报告
    https://github.com/anthropics/claude-code/issues/84072
  5. Claude Code GitHub issue #84442:Windows 原生版本通过明文 HTTP/1.1 分块代理流式失败的社区复现报告
    https://github.com/anthropics/claude-code/issues/84442
  6. Cloudflare Workers Streams:使用 ReadableStream 保持响应流式传输(官方工程文档)
    https://developers.cloudflare.com/workers/runtime-apis/streams/
  7. 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 文档用于核对协议、配置和错误语义,不表示它们已确认本文所述具体组合的根因。

相关阅读