☰
OpenClaw 1008报错排查:gateway token认证失败详解
2026/10/5 8:35:40 网站建设 项目流程

如果你最近在折腾 OpenClaw——社区里习惯叫它“龙虾”——十有八九会被一个报错卡住:disconnected (1008): unauthorized: gateway token。我第一次遇到是在 Windows 上用 WSL2 部署的时候,CLI 刚起来,任务还没跑两秒,终端就弹出这么一行,随后进程直接退出。当时网上一搜,一半结果在讲“你是不是 API key 写错了”,另一半在讲“网络断了重连”,跟这个 1008 完全对不上。这篇就把我这次完整的排查链路写下来,包括 1008 到底是什么、gateway token 从哪里来、怎么生成和写入、如何验证,以及几个经常一起出现的“亲戚”报错怎么区分。无论你是刚部署 OpenClaw 的新手,还是升级后突然报这个错的老用户,都可以直接照着往下查。

1. 先分清“龙虾”在哪条链路上咬人:报错现场与三层结构

1.1 报错现场长什么样

先看报错本身。常见几种形态:

$ openclaw run "帮我整理一个周报" [INFO] openclaw version 0.4.2, platform linux-x64 [INFO] connecting to gateway wss://gw.openclaw.local:8443/v2 [ERROR] disconnected (1008): unauthorized: gateway token

也有时候报错会包装成任务失败的样子:

error running remote compact task: stream disconnected before completion: unauthorized (1008): gateway token

不论哪种形式,关键信息都是三个:disconnected、1008、unauthorized: gateway token。disconnected表示长连接被断开;1008是断开时的状态码;后面的字符串是网关给出的拒绝原因。它不是乱码,而是网关直接告诉你:“我没验证过你的 gateway token,所以我不放你进来。”

1.2 三层连接:客户端、网关、模型

要理解这个报错,先得把 OpenClaw 的连接链路理顺。它的基础结构可以简化成三层:

  • 客户端:你敲命令的 CLI,或者跑着任务的编排进程。
  • 网关:负责转发指令、管理长连接、做统一认证的中间层。它可以是官方托管的网关,也可以是你自建的网关服务。
  • 模型服务:真正干活的推理服务,比如本地 Ollama、通过 OpenAI 兼容接口托管的模型等。

每一跳都用不同的凭证:

  • 客户端到网关:用 gateway token,验证“你这个客户端有没有权限使用这个网关”。
  • 网关到模型服务:用模型 API key,验证“网关有没有权限调用模型”。

也就是说,哪怕你本地的模型 API key 完全正确,一旦网关不认你的 gateway token,依然会在第一跳被卡住。很多同学第一反应是去检查自己的模型密钥,完全忽略了还有网关这一层,于是来回改配置都无效。

1.3 为什么网关不直接给你返回 401

这里有一个容易困惑的点:REST 接口如果没权限,通常会返回 HTTP 401。但 WebSocket 建立连接时,网关会先完成 HTTP Upgrade 握手,再在握手完成后立刻用关闭帧断开。也就是说,认证失败发生在 WebSocket 协议层,而不是 HTTP 状态码层。所以你看到的是disconnected (1008),而不是401 Unauthorized。

这也解释了为什么你在浏览器开发者工具里可能看到“WebSocket connection failed”一类的提示,而不是一个明确的 401。协议层把“认证失败”这件事表达成了“连接被策略拒绝”,这在排错时很容易让人觉得是网络问题。

2. 1008 这个状态码的门道:策略违规、无效令牌和绑定关系

2.1 RFC 6455 里的 policy violation

WebSocket 标准协议 RFC 6455 定义了一组关闭状态码,1008 官方含义是 Policy Violation。简单说,服务端认为“你的连接请求违反了它的策略”,于是主动关断。它和 1006(连接异常中断,没有收到关闭帧)、1011(服务端内部错误)都不一样。

打个比方:REST 世界的 401 像门禁读卡器说“你卡无效”;WebSocket 的 1008 则像门禁读卡器说“你根本没权限进这栋楼”。门没坏,网络也通,纯粹是这扇门不给你进。

2.2 gateway token 失效的常见原因

结合我在 OpenClaw 社区和自身环境里看到的案例,gateway token 失效可以归结为下面几类原因:

原因现象常见动作
token 缺失配置里没写,或环境变量没加载补写配置
token 复制不完整从网页控制台复制时漏了字符重新复制
token 带引号/换行.env 里用了引号,shell 把引号也读进去了去掉引号
token 过期有的 token 默认 30 天有效重新生成
token 与客户端绑定不匹配生成的 token 绑定了固定设备 ID重新生成并绑定当前设备
网关地址不匹配官方网关 token 配到了自建网关上确认网关地址
token 权限不足token 只授权了某个 skill,但任务调用了别的范围提升权限或重新签发

我在后面第 3 章的排查过程里遇到的就是“带引号/换行”这一类。这是最容易被忽略、也最浪费时间的坑。

2.3 为什么别人电脑上能跑,你这里跑不通

如果你拿着一个在朋友电脑上能正常运行的配置,放到自己机器上却报 1008,不要急着觉得是系统不兼容。很大概率是 gateway token 和客户端之间存在绑定关系。OpenClaw 的网关在生成 token 时,可以选择绑定客户端指纹、设备 ID 或来源 IP。这么做是为了防止 token 被复制到别的机器上滥用。

所以,自己机器上的正确姿势是:在本机重新生成一个 token,而不是复制别人的。当然,绑定关系也可以在生成时关掉,但我不建议图省事关掉,尤其是当你的网关暴露在公网的时候。

3. 我这次的完整排查过程:从日志到根因,一步步来

3.1 第一件事:确认是必现还是偶发

遇到报错先别急着改配置。我习惯先连跑三次同样的任务,看报错是否必现。如果三次里只有一次报 1008,优先级最高的是检查网关是否重启、网络是否有抖动;如果每次必现,才进入配置排查。

我这次的情况是必现,每次启动都放在同一行报错。这就把范围缩小到了“网关认为 token 有问题”,而不是偶发的网络中断。

3.2 按加载顺序逐个排查配置来源

OpenClaw 的配置加载顺序一般是:CLI 参数 > 环境变量 > 配置文件 > 内置默认值。这意味着,如果你在 CLI 参数里传了一个错误 token,那环境变量里写得再对也白搭。所以排查时要按这个顺序反着来:

  1. 先看 CLI 启动脚本里有没有--gateway-token之类的参数;
  2. 再看环境变量里有没有OPENCLAW_GATEWAY_TOKEN,用env | grep -i openclaw看;
  3. 再看~/.openclaw/config.yaml或.env文件;
  4. 最后确认有没有系统服务(systemd、Windows 计划任务)在启动时覆盖了你的环境变量。

我这次是在一台 Ubuntu 服务器上部署,用 systemd 托管。一开始我看 systemd 服务文件里没写 token,但服务能起来,就以为没影响。后来才发现 systemd 服务默认不读取用户 shell 的环境变量,我在终端里export的OPENCLAW_GATEWAY_TOKEN根本没被服务拿到。这是很多自托管用户会踩的坑。

3.3 我的根因:.env 里的引号和隐藏字符

把 systemd 的环境变量问题解决后,报错依然在。我这才开始怀疑 token 本身。当时我用的.env文件是从网页控制台的“复制配置”按钮生成的,里面长这样:

OPENCLAW_GATEWAY_TOKEN="oclw_xxxxxx"

看着很正常,但问题恰恰出在这对双引号上。OpenClaw 的配置解析器在读取.env时,默认会保留引号作为值的一部分,而我在终端手动 export 时,shell 又会把引号吃掉。两种读法得到的结果不一致,网关那边自然不认。

为了确认,我执行了:

echo "$OPENCLAW_GATEWAY_TOKEN" | od -c

结果一眼就看清了:值首尾各多出一个",末尾还有一个看不见的换行。也就是说,发送给网关的 token 实际是"oclw_xxxxxx"(带引号),而不是oclw_xxxxxx。

去掉引号、确保.env文件里每个变量独占一行、结尾没有多余字符,再重新启动服务,报错立刻消失。整个过程大概花了四十分钟,实际根因就是一个引号。

3.4 排除“时间漂移”和“证书问题”

这里补充一个排查思路:如果 token 完全正确,但仍然报 1008,我建议顺手看看系统时间和网关时间是否一致。很多签名型 token 是带时效的,本机时间如果偏了好几分钟,网关会判定 token 已过期,同样以 1008 关闭连接。Linux 下用timedatectl status确认 NTP 同步状态,Windows 下用“设置 -> 时间与语言 -> 自动设置时间”确认。

另外,如果你的网关是自建的,并且走 HTTPS/WSS,证书链不完整也会导致握手异常。但这种情况通常会报证书错误而不是 1008,所以优先级往后放。

4. 修复 gateway token 的标准操作:生成、写入、验证三板斧

4.1 生成 token:CLI 和控制台两种方式

不同版本的 OpenClaw 命令略有差异,以你本版openclaw gateway token --help为准。我惯用的命令是这样的:

openclaw gateway token create --name my-dev --expires 30d

执行后命令行会输出一个类似oclw_xxxxxxxx的 token,并且只显示这一次。请立刻保存到你的密钥管理器里,不要贴在聊天工具中。如果你用的是官方托管网关,也可以登录网页控制台,在 Gateway Tokens 页面手动生成,还能选择绑定设备或绑定 IP。

CLI 方式和控制台方式的差异在于:CLI 生成后通常直接写进当前用户配置目录,控制台生成则需要你自己复制回本地配置。

4.2 写入配置:环境变量还是配置文件

我推荐的做法是优先使用环境变量,因为环境变量不会因为不同平台的配置路径差异而失效。示例:

export OPENCLAW_GATEWAY_TOKEN="oclw_xxxxxxxx"

如果你要长期使用,就写入.env文件:

OPENCLAW_GATEWAY_TOKEN=oclw_xxxxxxxx

注意:不要加引号,不要带注释,不要在行尾留空格。

如果你更习惯用配置文件,~/.openclaw/config.yaml里的写法类似:

gateway: token: oclw_xxxxxxxx

但请注意,OpenClaw 读取配置时会区分“字符串”和“带引号的字符串”。YAML 里如果写成token: "oclw_xxx"一般没问题,YAML 解析器会把引号当作字符串定界符;但.env格式没有这套规则,所以.env里一定不要加引号。

4.3 验证 token 是否真的生效

写完之后不要直接跑大任务,先用一个轻量命令验证:

openclaw gateway status

如果输出里能看到connected或authorized,说明网关这一跳已经通了。如果状态没变化,打开 debug 日志再看一遍握手过程:

OPENCLAW_LOG_LEVEL=debug openclaw run "ping"

debug 日志里,成功时会看到类似gateway authentication ok的记录;失败时会保留网关返回的关闭帧内容,方便你确认是 token 问题还是其他问题。

4.4 如果还不行,按这张表继续查

现象原因操作
能 ping 通网关但 1008token 权限不足或绑定不符重新生成一个默认全权限 token
网关地址连不上地址写错或端口不通核对 config 里的 gateway URL
刚改完配置仍报错旧进程还在跑杀掉进程重启,确认加载了新配置
局域网/公网访问异常代理或防火墙拦截 WSS临时关代理再试
时间不对导致 token 过期系统时钟漂移开启 NTP 同步后再试

5. 热搜里那些“亲戚报错”:一眼分清是同一毛病还是新问题

在查资料的过程中,我发现很多人会把这几种报错混在一起聊。它们看起来都像“连接断了”,实际上原因完全不同,修法也不一样。

5.1 stream disconnected before completion 系列

OpenClaw 任务跑远程 skill 时,经常会出现这类带stream disconnected before completion的报错,后面跟着的具体原因各不相同:

  • stream closed before response.completed:通常是因为模型服务提前断开了 SSE 流,比如输出达到上限或服务端超时。
  • transport error: network error:多见于网络不稳定或网关负载高,偶发为主。
  • idle timeout waiting for sse:长时间没有新的数据帧到达,网关主动断开。可以检查模型端是不是卡在排队上。
  • 由于目标计算机积极拒绝,无法连接:这个一般是本地端口没监听,比如自建网关没启动。

这一类的共同点是:连接已经建立,但数据传输过程出了问题;而 1008 则是连接建立阶段就被拒绝。两者在日志里出现的位置不一样,修复思路也不一样。遇到这类问题,我一般先看日志里有没有 “connect to model service” 成功记录,再决定查网关还是查模型。

5.2 adb unauthorized 怎么解决

OpenClaw 如果要调度安卓设备,会用到 ADB。很多人在连接手机时报adb unauthorized,这个报错和 gateway token 没有关系,它表示 ADB 服务端已经发现设备,但设备端没有授权当前电脑的 RSA 指纹。解决办法很直接:手机屏幕上会弹出一个“允许 USB 调试”的对话框,点允许并勾选“一律允许”;如果没有弹窗,在电脑上执行adb kill-server && adb start-server再插入设备。

5.3 WSL2 环境验证

如果你的 OpenClaw 装在 Windows 的 WSL2 里,启动时报“无法安全验证 WSL2 环境”这类提示,最常见的是 WSL 内核版本过低。在 PowerShell 中运行:

wsl --status

如果提示内核需要更新,就执行wsl --update,然后重启 WSL。另外要注意 Windows 侧防火墙对 WSL 虚拟网卡的拦截,尤其是当你用localhost访问自建网关时,WSL2 的 NAT 网络可能会把 localhost 映射成不同的地址。遇到连不上,试着改用 WSL 的虚拟 IP 访问,或者用wsl hostname -I查看地址。

5.4 401 API key 和 1008 gateway token 的区分

这里单独把两个最像的报错列出来:

unexpected status 401 unauthorized: incorrect api key provided: sk-xxxx

和

disconnected (1008): unauthorized: gateway token

前者出现在“网关调用模型服务”这一跳,关键词是incorrect api key,后面跟的 key 是模型服务的 API key。修法是去模型服务控制台重新生成 key,并检查网关配置里的api_key或model_provider字段。

后者出现在“客户端连接网关”这一跳,关键词是gateway token。修法是按第 4 节的流程重新生成并配置 gateway token。

两个报错一字之差,一个在网关和模型之间,一个在客户端和网关之间,排查方向完全不同。我见过有人因为 401 报错反复重置系统,其实只要换一个 API key 就好了;也见过有人因为 1008 报错反复检查 API key,结果问题只是.env里的一个引号。

6. 几个我长期养成的实操习惯

最后分享几个我自己用着很顺手的习惯,算是给还没被这只“龙虾”咬过太多次的朋友一点预防针。

第一个习惯是统一用.env管理 token,不放散笔。OpenClaw 读取环境变量的路径是固定的,把OPENCLAW_GATEWAY_TOKEN、MODEL_API_KEY这些统一写进项目的.env,启动脚本里一律用set -a; source .env; set +a加载,能少踩很多“为什么我 export 了还是不行”的坑。

第二个习惯是定期轮换 token。我每个月一号会重新生成 gateway token,同时把旧的从配置里删掉。这么做一方面符合安全习惯,另一方面也能避免 token 过期时间不明确导致的尴尬——很多 token 生成时默认 30 天有效,你如果忘了,等到月末正好开始报 1008。

第三个习惯是遇到连接类报错,第一件事开 debug 日志。OPENCLAW_LOG_LEVEL=debug跑一条轻量任务,比瞎猜配置快得多。日志会明确告诉你连接到达了哪一层:是没连上网关,还是网关认证失败,还是模型调用超时。定位到层,问题基本解决一半。

第四个习惯是随时准备一个openclaw doctor命令做环境体检。很多版本都内置了类似命令,能一次性检查 WSL2 状态、网关地址、token 配置和模型服务可达性。虽然不能解决所有问题,但至少能帮你把最蠢的配置错误提前暴露出来。

我这台机器上第一次报 1008 到修好,前后花了不到一小时,其中大半时间花在一个引号上。回过头看,如果一开始就直接看环境变量的真实值,可能五分钟就结束了。希望这篇能帮你绕开我踩过的坑,看到disconnected (1008)的时候,先看一眼日志,再低头检查.env。很多时候,问题不在网络,也不在模型,就在那一行看起来人畜无害的配置里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询