From 082a8f6d810cd8a7e78b5a9860590055692d488f Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 23 Mar 2026 11:09:26 -0700 Subject: [PATCH] fix: startup error log + Windows exit handler for browse server On Windows, the CLI can't capture stderr from the server (stdio: 'ignore' required for process detachment). Write startup errors to .gstack/browse-startup-error.log so the CLI can report them on timeout. Also add process.on('exit') handler on Windows as defense-in-depth for state file cleanup (primary mechanism is CLI's stale-state detection). Co-Authored-By: Claude Opus 4.6 (1M context) --- browse/src/server.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/browse/src/server.ts b/browse/src/server.ts index 82af28bd..fe2c27cb 100644 --- a/browse/src/server.ts +++ b/browse/src/server.ts @@ -286,6 +286,13 @@ async function shutdown() { // Handle signals process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown); +// Windows: taskkill /F bypasses SIGTERM, but 'exit' fires for some shutdown paths. +// Defense-in-depth — primary cleanup is the CLI's stale-state detection via health check. +if (process.platform === 'win32') { + process.on('exit', () => { + try { fs.unlinkSync(config.stateFile); } catch {} + }); +} // ─── Start ───────────────────────────────────────────────────── async function start() { @@ -365,5 +372,14 @@ async function start() { start().catch((err) => { console.error(`[browse] Failed to start: ${err.message}`); + // Write error to disk for the CLI to read — on Windows, the CLI can't capture + // stderr because the server is launched with detached: true, stdio: 'ignore'. + try { + const errorLogPath = path.join(config.stateDir, 'browse-startup-error.log'); + fs.mkdirSync(config.stateDir, { recursive: true }); + fs.writeFileSync(errorLogPath, `${new Date().toISOString()} ${err.message}\n${err.stack || ''}\n`); + } catch { + // stateDir may not exist — nothing more we can do + } process.exit(1); });