garrytan/gstack · error · Error
[browse] Server unresponsive after retry — aborting
Error message
[browse] Server unresponsive after retry — aborting
What it means
Error "[browse] Server unresponsive after retry — aborting" thrown in garrytan/gstack.
Source
Thrown at browse/src/cli.ts:594
// #1781: a 30s timeout on a heavy page usually means busy, not dead.
// Don't kill a live server (that's what triggered the crash-loop) — report
// and exit so the user can retry rather than losing their (headed) window.
const ts = readState();
const alive = ts?.pid ? isProcessAlive(ts.pid) : false;
console.error(alive
? '[browse] Command timed out after 30s (server still alive — busy, not restarting). Retry, or raise load.'
: '[browse] Command timed out after 30s');
process.exit(1);
}
// Connection error — server may have crashed, OR may just be busy.
if (err.code === 'ECONNREFUSED' || err.code === 'ECONNRESET' || err.message?.includes('fetch failed')) {
const oldState = readState();
// #1781 busy-vs-dead: a single-threaded daemon under beacon/extension load
// can briefly stop answering HTTP while still alive. Before declaring a
// crash, if the process is alive give /health a bounded chance to recover
// and just retry the command — never kill+restart a live-but-busy server.
if (oldState?.pid && isProcessAlive(oldState.pid) && await probeHealthWithBackoff(oldState.port)) {
if (retries >= 1) throw new Error('[browse] Server unresponsive after retry — aborting');
console.error('[browse] Server was briefly unresponsive (busy); retrying command...');
return sendCommand(oldState, command, args, retries + 1);
}
// Truly dead (or health never recovered) → restart.
if (retries >= 1) throw new Error('[browse] Server crashed twice in a row — aborting');
console.error('[browse] Server connection lost. Restarting...');
if (oldState && oldState.pid) {
await killServer(oldState.pid);
}
// startServer() now clears the Chromium SingletonLock + reaps the orphan,
// so the relaunch isn't blocked by the dead Chromium's profile lock (#1781).
//
// Reapply --proxy / --headed when restarting. headed comes from THIS
// invocation OR the persisted server mode, so a restart triggered by a
// plain command (goto/status, no --headed) never silently downgrades a
// headed session to headless (#1781). Same for proxy/configHash.
const restartEnv = buildRestartEnv(_globalFlags, oldState);
const newState = await startServer(Object.keys(restartEnv).length ? restartEnv : undefined);View on GitHub (pinned to 94993f7401)
When it happens
Trigger: Thrown at browse/src/cli.ts:594 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/bcd94384f8156586.
Report an issue: GitHub.