{"record":{"id":"7e0aab9de3c9c021","repo":"garrytan/gstack","slug":"browse-server-crashed-twice-in-a-row-aborting","errorCode":null,"errorMessage":"[browse] Server crashed twice in a row — aborting","messagePattern":"\\[browse\\] Server crashed twice in a row — aborting","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/cli.ts","lineNumber":599,"sourceCode":"      console.error(alive\n        ? '[browse] Command timed out after 30s (server still alive — busy, not restarting). Retry, or raise load.'\n        : '[browse] Command timed out after 30s');\n      process.exit(1);\n    }\n    // Connection error — server may have crashed, OR may just be busy.\n    if (err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET' || err.message?.includes('fetch failed')) {\n      const oldState = readState();\n      // #1781 busy-vs-dead: a single-threaded daemon under beacon/extension load\n      // can briefly stop answering HTTP while still alive. Before declaring a\n      // crash, if the process is alive give /health a bounded chance to recover\n      // and just retry the command — never kill+restart a live-but-busy server.\n      if (oldState?.pid && isProcessAlive(oldState.pid) && await probeHealthWithBackoff(oldState.port)) {\n        if (retries >= 1) throw new Error('[browse] Server unresponsive after retry — aborting');\n        console.error('[browse] Server was briefly unresponsive (busy); retrying command...');\n        return sendCommand(oldState, command, args, retries + 1);\n      }\n      // Truly dead (or health never recovered) → restart.\n      if (retries >= 1) throw new Error('[browse] Server crashed twice in a row — aborting');\n      console.error('[browse] Server connection lost. Restarting...');\n      if (oldState && oldState.pid) {\n        await killServer(oldState.pid);\n      }\n      // startServer() now clears the Chromium SingletonLock + reaps the orphan,\n      // so the relaunch isn't blocked by the dead Chromium's profile lock (#1781).\n      //\n      // Reapply --proxy / --headed when restarting. headed comes from THIS\n      // invocation OR the persisted server mode, so a restart triggered by a\n      // plain command (goto/status, no --headed) never silently downgrades a\n      // headed session to headless (#1781). Same for proxy/configHash.\n      const restartEnv = buildRestartEnv(_globalFlags, oldState);\n      const newState = await startServer(Object.keys(restartEnv).length ? restartEnv : undefined);\n      return sendCommand(newState, command, args, retries + 1);\n    }\n    throw err;\n  }\n}","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/cli.ts#L581-L617","documentation":"Error \"[browse] Server crashed twice in a row — aborting\" thrown in garrytan/gstack.","triggerScenarios":"Thrown at browse/src/cli.ts:599 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}