Repository navigation
桌面端反复重启后必定启动失败:dsh-auth cookie 随随机端口无限堆积,撑爆 16KB 请求头上限导致 431 #11624
Replies: 4 comments
|
你的推导我逐条核了,都对,只在修法上补一个坑。 代码侧对得上(master
所以"必然而非偶发"这个判断成立, 补的坑在修法方向:不要用"名字里去掉端口"来修。 最小修法是写入时清理同族旧名:签发新 cookie 之后,把其它 恢复你现在的做法(关掉应用,删 |
|
多谢逐条核对,特别是修法方向那段——我之前提的"名字去端口"确实想漏了, 补一条现场验证,正好把你给的算法闭环了。 按
所以"端口进名字 → 每次启动必然新增一条 → 永不覆盖 → 累积到 70 条撞 16KB 关于你给的最小修法(签发新 cookie 后把其它 另外这个 workaround 我已经做成脚本常备了(关应用 → 删 Network/Cookies), |
|
补充另一个失效面:这台机器上除了 431,还有一条 环境:DSH Desktop 0.2.1-rc.2(Windows 11 x64 / Electron 44.7.0 / Node 24.21.0),
同目录另有 5 份是主帖那种
第 1 条依赖机器配置:undici 用户侧规避(两条都能治):把 Host 监听端口钉死,桌面端可在 profile 的 端口固定后 cookie 名稳定(同名覆盖、不再累积),也不会再落进 badPorts。 建议修复: |
|
@LewisYa 这条是新信息,而且和 431 是两回事 —— 我在本地确认了机制。 Node 的 同一条命令、同样没人监听,只有名单里的端口会得到 两个失败共享同一个起点(
用户侧能做的:把动态端口段改回 Windows 默认的 49152 起( |
Uh oh!
There was an error while loading. Please reload this page.
环境
摘要
桌面端每次启动都会写入一个新的 dsh-auth-<44位哈希> 会话 cookie。
哈希值包含当次启动的随机端口,而 cookie 按域名(127.0.0.1)存储、
不区分端口,因此旧 cookie 永远不会被同名覆盖,只会无限累积。
累积到约 70 条时,Cookie 请求头超过 Node 默认的 max-http-header-size
(16384 字节),Host 返回 431,桌面端将其判为认证失败并中止启动。
现象
启动即弹窗 "The application could not start or stopped unexpectedly.",详情为:
Error: desktop welcome: Web authentication failed
at connectDesktopWelcome (.../app.asar/lib/main.js)
at async Object.start (.../app.asar/lib/main.js)
日志中 phase: startup。
弹窗建议"重装或禁用第三方插件",这两条都是死路,与插件无关。
复现步骤
实测证据
从 cookie 库 Network/Cookies 中统计,故障时 127.0.0.1 下共有
71 条 dsh-auth-* cookie,无其他任何 cookie。
单条 cookie 形态(实测 Set-Cookie):
dsh-auth-xve1cdvif713tCh-zvXXZ2XqUnAtUVDatWsduYXhYok=v1.eyJ2ZXJzaW9uIjoxLCJhdXRob3JpdHkiOiIxMjcuMC4wLjE6NDk0OTQifQ.rnymiz...
Max-Age=2592000; Path=/; HttpOnly; SameSite=Strict
针对真实 Host 扫描条数临界点(仅构造 Cookie 头,其余请求头最小化):
Cookie 条数 Cookie 头字节 响应
71 16,194 200
72 16,422 431
实际请求还会带上 Host、User-Agent、Accept、Sec-Fetch-* 等约 300 字节,
因此真实阈值落在 71 条,与用户实际故障点完全吻合。
根因分析
app.asar/lib/main.js 中的启动流程:
const ready = await host.start();
hostCookie = await authenticateWebHost(ready.url); // ① 通过
hostUrl = ready.url;
welcomeBackend = await connectDesktopWelcome(
ready.url, (input, init) => net.fetch(input, init), ...
); // ② 失败
① authenticateWebHost() 使用 Node 全局 fetch,请求不带任何 cookie,
因此能正常拿到 303 + Set-Cookie,看起来一切正常。
② connectDesktopWelcome() 使用 Chromium 的 net.fetch 且 credentials: "include",
会把该域下全部 71 条 cookie 一并发出,请求头超限 → Host 返回 431:
const authenticated = await send(authenticatedUrl, { credentials: "include" });
if (!authenticated.ok) throw new Error("desktop welcome: Web authentication failed");
431 被统一归入 !ok,真实状态码被吞掉,日志中只剩"认证失败",极难定位。
为什么 Web 版不会遇到
三个条件在 Web 版被默认用法消掉了:
桌面端则相反:端口必须每次随机(无法假设某个端口空闲)、cookie 存在
应用内置 profile 里无人清理、失败被包装成误导性的启动崩溃弹窗。
建议修复(按优先级)
authority 信息已包含在 value 内,无需体现在名字里
desktop welcome: Web authentication failed (HTTP 431),
并在致命弹窗中区分该场景,提示"清理会话 cookie"而非"重装"
临时规避
关闭应用(含托盘)后删除:
%APPDATA%@deepseek-ai\dsh-desktop\Network\Cookies
%APPDATA%@deepseek-ai\dsh-desktop\Network\Cookies-journal
该库仅包含上述 localhost dsh-auth cookie,不影响账号登录态
(凭据存于 ~/.dsh)。
清理后大约可再用 70 次启动,之后复发。
补充
如果你也遇到同样的报错,可以核对一下 cookie 库里的条数。
只要 127.0.0.1 下的 dsh-auth-* 接近 70 条,基本就是这个原因,
清掉即可恢复,无需重装。
All reactions