garrytan/gstack · error · Error

Server failed to start within ${MAX_START_WAIT / 1000}s

Error message

Server failed to start within ${MAX_START_WAIT / 1000}s

What it means

Error "Server failed to start within ${MAX_START_WAIT / 1000}s" thrown in garrytan/gstack.

Source

Thrown at browse/src/cli.ts:372

    if (state && await isServerHealthy(state.port)) {
      return state;
    }
    await Bun.sleep(100);
  }

  // Server didn't start in time — check the on-disk startup error log.
  // Both platforms now spawn with stdio: 'ignore', so the server writes
  // errors to disk for the CLI to read (see server.ts start().catch).
  const errorLogPath = path.join(config.stateDir, 'browse-startup-error.log');
  try {
    const errorLog = fs.readFileSync(errorLogPath, 'utf-8').trim();
    if (errorLog) {
      throw new Error(`Server failed to start:\n${errorLog}`);
    }
  } catch (e: any) {
    if (e.code !== 'ENOENT') throw e;
  }
  throw new Error(`Server failed to start within ${MAX_START_WAIT / 1000}s`);
}

/**
 * Acquire an exclusive lockfile to prevent concurrent ensureServer() races (TOCTOU).
 * Returns a cleanup function that releases the lock.
 */
function acquireServerLock(): (() => void) | null {
  const lockPath = `${config.stateFile}.lock`;
  try {
    // 'wx' — create exclusively, fails if file already exists (atomic check-and-create)
    // Using string flag instead of numeric constants for Bun Windows compatibility
    const fd = fs.openSync(lockPath, 'wx');
    fs.writeSync(fd, `${process.pid}\n`);
    fs.closeSync(fd);
    return () => { safeUnlink(lockPath); };
  } catch {
    // Lock already held — check if the holder is still alive
    try {

View on GitHub (pinned to 94993f7401)

When it happens

Trigger: Thrown at browse/src/cli.ts:372 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/e4b302ae35ca5093. Report an issue: GitHub.