Repository navigation
Desktop startup crash loop: Web authentication failed (0.2.2-rc.1) #12502
Replies: 6 comments
|
Same crash here on macOS (Apple Silicon) with the officially notarized 0.2.2-rc.1 — and we isolated the root cause. The stack matches exactly ( Root cause
// ~16857
const authenticated = await send(authenticatedUrl, { credentials: "include" });
await authenticated.body?.cancel();
if (!authenticated.ok) throw new Error("desktop welcome: Web authentication failed"); // 303 is not ok -> throw// ~20387
welcomeBackend = await connectDesktopWelcome(
ready.url,
(input, init) => net.fetch(input, init), // net.fetch drops SameSite cookie on 303
async () => (await session.defaultSession.cookies.get({ url: ready.url }))
.map(c => `${c.name}=${c.value}`).join("; ")
);Because this throws very early inside Suggested fix
Workaround (reference only, not a recommendation)Patching |
Definitive root cause (confirmed on 0.2.2-rc.1, macOS arm64)This is not a plugin problem and not a 303-handling problem. The Host returns 431 Request Header Fields Too Large because the Electron default session has accumulated one
Measured on the affected machine:
Correction to the earlier comment: the 303 is handled correctly — Upstream fix (already on master, not in 0.2.2-rc.1)
Workaround for affected usersQuit the app and delete the accumulated cookies once; startup returns until ~70 more launches: sqlite3 "$HOME/Library/Application Support/@deepseek-ai/dsh-desktop/Cookies" \
"delete from cookies where host_key='127.0.0.1' and name like 'dsh-auth-%';"(Backporting the two commits also works, but needs an ad-hoc re-sign and is overwritten by auto-update.) Please ship these two commits in the next RC — the cookie leak alone makes every long-lived desktop install fail after roughly 70 launches. |
|
Confirming on my machine (the original reporter): the 431 cookie-accumulation analysis is correct for the persistent variant, and the two master commits exist, but my crash was a different, transient trigger. Some data from this side: 1. The fix commits are real, and my 0.2.2-rc.1 build does not include them. 2. This 431 root cause does not explain my original crash. 3. But the leak is real and already ticking on my machine too. Thanks for the thorough isolation — the request-header-size repro (226-byte → 200, 17,588-byte → 431) is the key evidence. Agreed these two commits should land in the next RC. |
Independent Windows verification: same root cause, reproduced end-to-endConfirming the 431 / Environment
1. Same failure signature Note that the crash log itself contains no 2. Cookie DB measurements (71 rows, byte-exact) Concatenated as a single 3. Naming is authority-bound, which is why they never get cleaned up Verified in the shipped const COOKIE_PREFIX = "dsh-auth-";
function cookieName(authority) {
return COOKIE_PREFIX + encodeBase64Url(createHash("sha256").update(authority).digest());
}
args: ["--no-open", "--host", "127.0.0.1", "--port", "0"]so every launch yields a fresh random port → fresh authority → fresh cookie name → a new row appended, none of the old ones removed. The documented behaviour agrees: cookies "bind the normalized hostname plus port in both their deterministic name and signed payload." 4. Threshold reproduced against a live 0.2.2-rc.1 Host Rather than only testing the two extremes, I bisected the cookie count against a running Host (
The transition sits between 68 and 71, i.e. exactly at the 16,384-byte boundary — the leak is monotonic and the last few launches are what cross the line, which is why installs "work for a while, then never start again." 5. Local build genuinely lacks both fixes
hostCookie = await authenticateWebHost(ready.url); // cookie already obtained here
hostUrl = ready.url;
...
welcomeBackend = await connectDesktopWelcome(ready.url, (input, init) => net.fetch(input, init), async () => ...);
One correction to my own earlier assumption, in case others are reading: the "Disable third-party plugins" button cannot help here, because the handshake aborts at Request: please ship For anyone hitting this on the way to a fixed build, the one-time cleanup quoted by @HuHong-Tao works on Windows as well, with the DB at |
|
Confirmed on 0.2.2-rc.1 (notarized, macOS arm64, 2026-11-08): identical stack ( Two additions beyond #12377 / #11758: 1. Byte-exact accounting of the cookie jar. Summing the Cookies SQLite DB: 71 rows matching 2. The jar stops storing after the threshold. Polling the Cookies DB at 0.5 s intervals during failing launches shows zero new Workaround until a fix ships — quit the app, then: sqlite3 ~/Library/Application\ Support/@deepseek-ai/dsh-desktop/Cookies \
"DELETE FROM cookies WHERE name LIKE 'dsh-auth-%' AND host_key='127.0.0.1';"At ~262 bytes per launch it recurs after roughly 70 more launches. Pruning stale |
|
The 431/cookie chain is now confirmed across this thread, #12360, and #12606. Two facts from the source side that close the loop: 1. The fixes exist in 2. The prune still had one ordering hole. On master,
Workaround for affected users today (until a desktop build includes the two commits): close DSH fully (tray → exit), then remove the accumulated cookies from If maintainers want, the two ordering/branch changes can be cherry-picked independently of the build-pipeline fix. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
DSH desktop 0.2.2-rc.1 crashed 5 times in a row at startup (2026-11-07 09:17:52–09:32:43 UTC+8). The crash dialog offered two buttons: "Restart" and "Disable third-party plugins". After the first crash I clicked "Disable third-party plugins"; the next 4 crashes still happened, so the issue is unrelated to third-party plugins.
Error
All 5 crash logs show the exact same stack:
The Electron main process starts a Desktop Host child, receives an authenticated
ready.url(e.g.http://127.0.0.1:<port>/?token=...), then callsconnectDesktopWelcome()with anet.fetchthat is supposed to return200after following the303set-cookie redirect. During the crash window that request failed (returned non-2xx).What I ruled out
cordis.patch.yml(13 entries, 28931 bytes) into a separate test profile and booted it directly with thedsh-desktop-hostentry. It reacheddsh web: http://127.0.0.1:57023/?token=...and loaded all providers/models.scutil --proxyshowed all proxy modes disabled; Clash Verge had no active process.The problem resolved only after a full process restart at 09:38 (new
SingletonLockPID). It looks like an internal race in the desktop startup handshake between the Electron main process and the Desktop Host child.Side effect: user patch got overwritten
After clicking "Disable third-party plugins", DSH rewrote
cordis.patch.ymlto an 828-byte minimal version containing only:agent-default-modelui-settings-accountui-chatui-settingsAll other configured entries (
llm-pi-ai,model-router,dsh-connect-workbuddy,dsh-dafeiyu,permission, etc.) were silently dropped. Fortunately DSH had auto-backed up the previous patch ascordis.patch.yml.bak-<timestamp>, so I could restore it.Requests
cordis.patch.ymlwhen the user clicks "Disable third-party plugins"; instead move third-party entries todisabled: true, or ask for confirmation.cordis.patch.yml.bak-*backups so users know they can restore after a crash.Environment
~/.dsh/profiles/desktop~/Library/Logs/DeepSeek Harness/crash-2026-11-07T01-1*.logAll reactions