我把 Windows 上的 opencode free 无响应问题,硬生生排查到了根因

最近我在一台 Windows 电脑上使用 opencode 时,遇到一个很别扭的问题:free 模型在另一台电脑上能正常用,但在这台机器上就是不回消息,或者只显示一行 build,像是卡住了一样。

一开始我也怀疑过最常见的几种原因,比如网络不通、安装损坏、缓存脏了、版本太旧,甚至怀疑是不是这台电脑环境有问题。结果一路排下来才发现,这次问题并不在“电脑坏了”,而是在 opencode 客户端和它官方 free 通道之间,出现了协议兼容问题。

这篇文章不讲玄学修复,主要记录我这次完整的排障过程:我最开始是怎么误判的,哪些证据真正把问题钉死了,为什么重装没有用,以及最后我是怎么临时把它救活的。

先交代一下我的运行环境

为了避免“你这是不是个例环境”的疑问,先把我这次出问题时的环境列出来。

  • 操作系统:Windows 11 专业版 64 位
  • 系统版本:10.0.26200
  • opencode 版本:1.17.13
  • 本机 Node.js 版本:v22.22.3

另外还有一个很关键的对比条件:我在另一台电脑上使用同版本 opencode 时,free 模型是可以正常工作的。

也就是说,这次问题并不是一个特别老旧的版本或者明显异常的环境里出现的,也不是账号本身彻底不可用。

现象很简单,但很容易误导人

问题最初的表现并不复杂。

我在这台 Windows 电脑上用 opencode 调 free 模型时,经常会出现下面几种情况:

  • 没有正文回复,像是卡住了
  • 日志里只停在模型开始构建的阶段
  • 有时直接报错,有时又像“没报错但也没结果”

更容易让人误判的是,另一台电脑上的 opencode free 又是正常的。

这会让人本能地怀疑两件事:

  • 这台电脑的安装坏了
  • 这台电脑的网络或者环境有问题

但这两个方向,最后都不是根因。

第一轮排查:我先把最常见的问题排除了

先说结论:这次不是简单的安装损坏,也不是官方接口彻底挂了。

我最开始做了几件很常规的事:

  • 检查本地是否有多个 opencode 安装来源
  • 清掉残留进程和用户目录缓存
  • 升级 opencode 到较新的版本
  • 直接重装 opencode

这些操作都做过之后,问题依旧存在。

如果只停在这里,很容易得出一个错误结论:这台电脑环境有毒,或者 Windows 对 opencode 支持不稳定。

但继续往下查时,我发现一个关键事实:官方接口本身其实是通的。

第二轮排查:接口能通,不代表客户端吃得下

为了排除是不是官方服务挂了,我没有只看 opencode 自己的输出,而是绕过客户端,直接去请求官方接口。

结果很关键:

  • 模型列表接口能正常返回
  • 普通请求能返回
  • 流式请求也能返回

这说明一件事:官方 free 通道并不是完全不可用。

也就是说,问题不在“没有响应”,而在“opencode 自己没有正确处理响应”。

这一步把排查方向彻底改了。

从这里开始,我不再把重点放在“重装”和“换网络”,而是转向了协议层排查。

真正的突破点:抓到了一条不该被忽略的流事件

后来我在本地加了一个中间代理,专门把 opencode 发出的请求和官方接口返回的流式内容完整记下来。

这一抓,问题就明朗了。

官方 free 模型返回的流,前半段看起来完全正常。正文会一段一段往外推,比如:

  • response.output_text.delta
  • response.completed

但在回答结束之后,流里还会多出一条额外事件。内容大意是:

{
  "choices": [],
  "x-opencode-type": "inference-cost",
  "cost": "0.00000000"
}

这条事件不是普通用户会关心的内容,但它对客户端来说非常致命。

因为 opencode 底层会把流式返回当成标准事件来做类型校验,而这条 x-opencode-type: "inference-cost" 并不符合它当前期待的标准结构。结果就是:

  • 客户端把这条额外事件当成“坏数据”
  • 类型校验失败
  • 请求流程中断
  • 表面上看起来就像“free 模型无响应”

换句话说,这次真正的问题不是模型不返回,而是模型返回了一个客户端当前没兼容好的扩展事件。

为什么这件事特别容易把人带偏

这个问题最麻烦的地方,不是它难,而是它特别像别的问题。

它会同时伪装成下面几种情况:

  • 像网络问题,因为有时会报连接异常
  • 像安装问题,因为重装前后表现差不多
  • 像模型宕机,因为用户看到的就是没回复
  • 像 Windows 环境问题,因为别的电脑又能正常用

但如果直接看原始流,会发现它其实是“返回格式兼容失败”。

这也是为什么很多人会在这种问题上来回兜圈子:删缓存、换版本、重启电脑、重装软件,表面上都像合理动作,但它们碰不到真正的根。

为什么重装没用

这个问题我最后能下结论,是因为我真的做过完整重装,而且重装后照样复现。

原因很简单。

如果根因是:

  • 官方接口返回了客户端没兼容好的扩展流事件
  • 或者客户端当前版本对某种响应结构解析不完整

那么你重装回来,装的还是同一套客户端逻辑,它当然还会继续复现。

重装能解决的是:

  • 安装文件损坏
  • 旧缓存污染
  • 残留进程占用
  • 路径冲突

但解决不了协议不兼容。

所以这类问题里,重装最多只能“排除一部分可能性”,不能当成真正的修复手段。

问题并不只停在第一轮请求

我后面继续往下查时,还发现这个问题不是只有“第一问有没有回复”这么简单。

就算我通过本地代理先把那条异常流事件过滤掉,让第一轮请求能够正常结束,后面继续使用同一个 session 发送第二问时,仍然可能失败。

原因在于多轮对话历史。

为了让第一轮结果能被正常显示,我在代理里把一部分返回格式做了标准化。这样做本身没错,但 opencode 在继续 session 时,会把上一轮 assistant 消息原样带回官方接口。结果官方接口又不接受这种历史消息结构,第二轮就会直接报 400。

也就是说,这次问题不是单点故障,而是连着暴露了几层兼容性问题:

  • 官方 free 流里多了一条客户端没兼容好的扩展事件
  • opencode 默认输出层没有稳定把正文渲染出来
  • 多轮 session 的 assistant 历史格式,也和上游接口预期不完全一致

这也是为什么它表现出来会时好时坏,看上去非常不稳定。

我最后是怎么临时修好的

既然根因已经不是“电脑坏了”,那解决思路也就清楚了:在客户端和官方接口之间,补一层兼容代理。

这层代理做了几件事:

  • 把 opencode 的请求先发到本机
  • 再由本机转发到官方接口
  • 过滤掉会导致类型校验失败的扩展流事件
  • 把响应流改写成客户端更容易接受的格式
  • 在多轮对话时,把 assistant 历史消息压平成上游能接受的内容
  • 在上游偶发失败时做重试和标准错误返回

这不是“官方修复”,而是本地临时兼容方案。

但它有一个现实好处:能让问题真正可用,而不是一直停留在理论分析。

这次排查给我的最大结论

如果你也遇到类似情况,不要急着把问题归因到“Windows 不行”或者“这台电脑坏了”。

更准确的说法是:

这次出问题的是 opencode 客户端和官方 free 通道之间的兼容细节,而不是用户的基本操作有问题。

我这次排查下来,最关键的结论有三个:

  1. 官方接口能通,不代表 opencode 就一定能正确消费返回流。
  2. 重装只能排除安装层问题,碰不到协议兼容问题。
  3. 遇到“明明有返回,但客户端像没回复”这种现象时,抓原始流比反复重装更有价值。

如果你也遇到了类似问题,可以怎么判断

你可以先用下面这个思路快速判断自己是不是遇到了同类问题:

  • 另一台电脑可以用,这台电脑不行
  • 重装后仍然复现
  • 有时只看到构建提示,看不到正文
  • 偶尔出现奇怪的泛化报错,而不是清晰错误信息
  • 第一轮偶尔能成,继续问第二轮又不稳定

如果这些现象高度重合,那么问题大概率不是简单的“装坏了”,而是兼容层出了问题。

最后

这次问题最有意思的地方在于,它表面上是一个“客户端没回复”的小故障,但一路查下去,最后会落到非常具体的协议细节上。

对普通用户来说,这件事的结论其实很简单:别把时间全浪费在重装上。

对我自己来说,这次排查也算是一个提醒:

当一个 AI 工具“看起来像没响应”时,真正出问题的未必是模型本身,也未必是网络,很多时候只是客户端和上游之间某个很细的小协议点没对齐。

而一旦不把这个点抓出来,后面的所有操作都只是在碰运气。

更多推荐