DeepSeek Harness 报 Web authentication failed:cookie 431 怎么修
DeepSeek Harness 桌面端用着用着突然打不开,日志里只有一句 desktop welcome: Web authentication failed,卸载重装、换账号、换密钥都不管用——这类案例里最常见的原因不是认证坏了,而是本地 dsh-auth-* cookie 每次启动新增一条,约 70 条后把 Cookie 请求头撑过 Node 默认的 16,384 字节,Host 在 welcome 处理之前就直接回了 431。 本文不讲空泛的「清缓存」,而是按「先证明是头部超限 → 再选一种恢复方式 → 最后处理复发」的顺序走一遍,每一步都能自己验证(#10831、#11366)。
DeepSeek Harness 先分清:认证失败提示不等于密钥或账号有问题
Web authentication failed 是 welcome 流程的统一错误文案,401 和 431 都会落到这句话上;只有看到 431 或请求头体积证据,才能判定是 cookie 累积。
先把三种常见情况分开,避免一上来就重装:
- 凭据问题:通常发生在模型请求阶段,日志里会出现
MISSING_CREDENTIAL、401 或某个 provider 的名字,界面还能打开。 - 端口/地址问题:
dsh web场景下没使用终端打印的带 token 地址,提示会明确让你重新打开 URL。 - 请求头超限:桌面端连启动窗口都出不来,日志停在
connectDesktopWelcome,并且重装无效——就是本文这一类。
确认只需要三步:
- 完全退出 DSH,包括托盘图标和后台残留进程;确认任务管理器里没有
DeepSeek Harness相关进程。 - 找到 cookie 库:Windows 在
%APPDATA%\@deepseek-ai\dsh-desktop\Network\Cookies,macOS 在~/Library/Application Support/@deepseek-ai/dsh-desktop/Network/Cookies。 - 用任意 SQLite 工具执行
SELECT COUNT(*) FROM cookies WHERE host_key LIKE '%127.0.0.1%' AND name LIKE 'dsh-auth-%';,结果接近 70 就是它。
DSH插件 根因:cookie 名带端口,每次启动都新增一条
cookie 名 = dsh-auth- + base64url(sha256(Host authority)),而桌面端每次启动使用随机端口,所以名字每次都不同;写入只设 30 天 Max-Age,没有任何删除旧名的路径。
这条链路可以拆成四步:
- 桌面端启动本地 Host,监听
127.0.0.1的随机端口。 - welcome 流程用当前 authority 计算 cookie 名,签发一条新的
dsh-auth-*。 - 浏览器 cookie 库按「域名 + 路径 + 名字」存储,名字不同就是新的一行,旧行继续保留。
- 下次启动再换端口,再新增一行;累积到约 70 条时,Cookie 头超过 16,384 字节,Host 返回 431。
体积可以自己算:社区实测每条约 226 字节(52 字节名字 + 1 字节等号 + 173 字节值),71 条加上 70 个 ; 分隔符就是 16,186 字节,已经超过 Node 默认上限(#10828)。
| 启动次数 | Cookie 头体积 | 结果 |
|---|---|---|
| 60 条 | 13,824 B | 正常启动 |
| 64 条 | 约 14,700 B | 正常启动 |
| 65 条 | 约 14,900 B | 部分环境开始失败 |
| 71 条 | 16,186 B | 必然 431 |
关键点在于:旧 cookie 对服务端校验没有影响。authenticate() 只查找当前端口对应的那一条,剩下的 70 条纯粹是头部负担。所以「清掉旧 cookie 会不会影响认证」的答案是:不会,当前这次启动会重新签发(#11366)。
DeepSeek Harness 恢复:三种清法,按你能接受的风险选
最稳妥的是移走整个 Network/Cookies 文件;想保留其他站点 cookie 就只删 dsh-auth-* 行;只想先进得去、暂时不想动数据库,才用放大请求头上限的应急方案。
方法一:移走 cookie 库(推荐,失败可回滚)
- 完全退出 DSH,确认托盘和后台进程都结束。
- 进入
Network目录,把Cookies和Cookies-journal改名,例如加.bak后缀。 - 重新启动 DSH,应用会自动重建一个新的 cookie 库。
- 能进主界面后,再决定是否删除备份;如果启动仍失败,把备份改回原名即可回滚。
这个方法的代价是会清掉桌面端内嵌浏览器的所有站点 cookie,但对 DSH 自身没有影响:会话、插件、凭据都不在 cookie 库里。
方法二:只删 dsh-auth-* 行(保留其他 cookie)
- 退出 DSH,先复制一份
Cookies文件做备份。 - 用 SQLite 打开,执行:
DELETE FROM cookies
WHERE host_key LIKE '%127.0.0.1%'
AND name LIKE 'dsh-auth-%';
- 关闭数据库,重新启动 DSH。
- 如果启动成功,再观察下一次重启是否又新增一条;新增是正常的,说明机制仍在,只是计数被清零。
不要在应用运行时直接改这个库:SQLite 的 WAL 和内存缓存可能在退出时把旧行写回,出现「删了但没生效」。
方法三:临时放大请求头上限(只用于抢救数据)
- 关闭 DSH。
- 在启动环境里设置
NODE_OPTIONS=--max-http-header-size=131072。 - 启动 DSH,此时 71 条 cookie 也能被接受,先把需要的会话或文件导出。
- 处理完后仍然按方法一或方法二清理,不要长期靠这个变量运行。
这只是把天花板抬高,cookie 仍会继续累积;等累积到新上限,问题会原样回来。
DeepSeek插件 防复发:等官方修,还是先自己打补丁
官方截至社区复核时仍未修:rc.2、rc.3、rc.4 的 browser-auth.ts 命名与写入逻辑一致;社区补丁在 rc.4 上验证可以正常启动。
如果不想每次手动清,可以从三个方向处理:
- 启动时清理同族 cookie:在 Electron 载体启动阶段调用
session.clearStorageData({ storages: ["cookies"] })。社区在另一个同样以随机端口 attach runtime 的载体上用过,稳定运行数周;代价是清掉所有 cookie。 - cookie 名去端口化:把 authority 里的端口去掉再哈希,让同一台机器上的多次启动复用同一个名字,旧值被覆盖而不是新增。
- 启动时定向清理:保留去端口化之前的兼容逻辑,启动时删除所有「同域、
dsh-auth-前缀、但不是当前名字」的行,只清自己家的 cookie,不影响其他站点。
还有一个容易被忽略的改法:让 connectDesktopWelcome 在抛错时带上 HTTP 状态码。现在 401 和 431 共用一句 Web authentication failed,用户只能靠猜;把状态码带出来,至少能让人第一时间分清是凭据问题还是头部问题(#11408)。
DeepSeek Harness 注意事项:这几件事别做
下面这些做法会加重问题或掩盖真因,先避开再谈修复。
- 不要重装应用来「修」这个问题。cookie 库在 userData 目录,卸载通常不会清掉;重装后计数还在,看起来就像「重装无效」。
- 不要在运行中的 DSH 里删 cookie 文件。先完整退出,再操作,否则 WAL 可能把旧数据写回。
- 不要把
NODE_OPTIONS当成长期方案。它只是抬高上限,不解决累积。 - 不要同时开桌面端和
dsh web指向同一个DSH_HOME。两个实例会各自签发 cookie,累积速度翻倍,还会放大其他并发写问题。 - 清理前先备份。
Cookies文件和整个Network目录都不大,复制一份再动手,出问题能回滚。
如果你只是想让应用先打开,按「方法一」走一遍最快;如果你要判断自己是不是这一类,先数 cookie 条数,再看日志有没有 431。两个证据对上,就不用再在账号和密钥上浪费时间了。相关排查见 dsh web authentication required 报错?DeepSeek Harness 认证排查指引。
常见问题
先确认 DeepSeek Harness 的两个特征:一是重装、换密钥、换账号都无效,二是启动日志停在 connectDesktopWelcome,而不是模型请求阶段。进一步确认就数 cookie:完整退出 DSH 后打开 Network/Cookies 这个 SQLite 文件,统计 dsh-auth- 开头的行数,接近或超过 70 条基本就是请求头超限。
不会,DeepSeek Harness 的 dsh-auth-* 只是本地 Host 的一次性认证 cookie,删掉它不影响会话、插件或凭据。它属于 Network/Cookies 这个浏览器 cookie 库;会话日志在 sessions 目录,插件与凭据在 profile 和 .credentials.yaml 里,三者互不影响。清理后下次启动会用带 token 的地址重新签发一条新 cookie。
因为触发条件没消失:DeepSeek Harness 的 cookie 名由 Host authority 的哈希生成,而桌面端每次启动端口是随机的,所以每次启动都会新增一个不同名字的 dsh-auth-*,旧名字只设 30 天 Max-Age、没有任何删除路径。只清一次等于把计数归零,之后仍会按每次启动一条的速度重新累积。
DeepSeek Harness 的 rc.4 仍然没有修:按社区在 rc.4 上的复核,browser-auth.ts 的命名与写入逻辑未变,而社区补丁在 rc.4 上验证可以正常启动。0.2.2-alpha 线是否包含要按你实际安装的提交判断,不能只看版本号。升级后仍建议先清一次历史 cookie。
macOS 上 DeepSeek Harness 的认证 cookie 位置在桌面端 userData 目录下的 Network/Cookies(macOS 通常在 ~/Library/Application Support/@deepseek-ai/dsh-desktop/),清理逻辑一样:完全退出应用,备份 Cookies 与 Cookies-journal,再删除或改名,重启后会自动重建。不要在应用运行时直接删,SQLite 的 WAL 可能把旧行写回去。
相关术语
- dsh-auth-* cookie
- `dsh-auth-*` cookie 是 DeepSeek Harness 桌面端用于本地 Host 认证的 cookie,名字由 `dsh-auth-` 加 `base64url(sha256(Host authority))` 生成。authority 含随机端口,因此每次启动都会产生新名字;写入时只设 30 天 Max-Age,没有清理旧名的路径。— https://github.com/deepseek-ai/deepseek-harness/discussions/11366
- maxHeaderSize
- maxHeaderSize 是 Node.js 对单个 HTTP 请求头的默认大小上限,值为 16,384 字节。请求头超过该值时,HTTP 解析器直接返回 431,业务处理函数根本不会执行,所以这类失败常被上层包装成「认证失败」。— https://github.com/deepseek-ai/deepseek-harness/discussions/10828
- HTTP 431
- HTTP 431 是 HTTP 状态码 Request Header Fields Too Large 的编号,表示请求头字段过大。在 DeepSeek Harness 桌面端这个场景里,它由累积的 Cookie 头触发,而不是凭据无效或服务不可用。— https://github.com/deepseek-ai/deepseek-harness/discussions/10831
- connectDesktopWelcome
- connectDesktopWelcome 是桌面端启动时连接本地 Host 的 welcome 流程,负责带上认证 cookie 完成握手。它抛出的 `desktop welcome: Web authentication failed` 是上层统一错误,底层既可能是 401,也可能是 431,需要看状态码才能区分。— https://github.com/deepseek-ai/deepseek-harness/discussions/11408
来源
- #10831 — Startup fails with "Web authentication failed": local dsh-auth-* cookies accumulate on every restart· deepseek-ai(GitHub Discussions)
- #11366 — rc.2 / rc.3 均稳定复现:dsh-auth-* cookie 无限累积,约 70 次启动后必然启动失败· deepseek-ai(GitHub Discussions)
- #10828 — Desktop fails to start after ~70 launches: 实测边界正好是 16,384 字节· deepseek-ai(GitHub Discussions)
- deepseek-ai/deepseek-harness(源码仓库)· GitHub