gastownhall/beads · warning

server: DoltServer.Stop: %w

Error message

server: DoltServer.Stop: %w

What it means

Stop() runs a shutdown GC (DOLT_GC and DOLT_STATS_GC over a SQL connection) before killing the dolt child; this error wraps any failure from runShutdownGC. The returned error is an errors.Join of GC, wait, log-close, and pidfile-remove errors, so the stop itself still proceeds.

Source

Thrown at internal/storage/dbproxy/server/doltserver.go:351

		if time.Now().After(deadline) {
			return fmt.Errorf("listener not ready after %s: %w", startReadyTimeout, err)
		}

		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-s.egCtx.Done():
			return errors.New("dolt sql-server exited before listener became ready")
		case <-time.After(startReadyPollInterval):
		}
	}
}

func (s *DoltServer) Stop(ctx context.Context) error {
	gcErr := s.runShutdownGC(ctx)
	if gcErr != nil {
		gcErr = fmt.Errorf("server: DoltServer.Stop: %w", gcErr)
	}

	if s.cancel != nil {
		s.cancel()
	}
	var waitErr error
	if s.eg != nil {
		waitErr = s.eg.Wait()
		var exitErr *exec.ExitError
		if errors.As(waitErr, &exitErr) || errors.Is(waitErr, context.Canceled) {
			waitErr = nil
		}
	}
	if waitErr != nil {
		waitErr = fmt.Errorf("server: DoltServer.Stop: %w", waitErr)
	}
	var closeErr error
	if s.logFile != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check whether the error is connection-level — if the server is already dead, this is benign and the shutdown still completed.
  2. Retry Stop with a fresh, non-cancelled context so GC connections can be established.
  3. Run `CALL DOLT_GC()` manually via a SQL client to see the underlying GC error.
  4. Ensure no long-running queries/transactions are holding back GC before calling Stop.

Example fix

// before
ctx, cancel := context.WithCancel(ctx) // already-cancelled ctx starves shutdown GC
cancel()
_ = srv.Stop(ctx)
// after
gcCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Stop(gcCtx); err != nil {
    log.Warnf("stop returned errors: %v", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Only pass a live context to Stop; a cancelled ctx starves shutdown GC.
if ctx.Err() != nil {
    ctx = context.Background()
}

Try / catch

if err := srv.Stop(gcCtx); err != nil {
    if strings.Contains(err.Error(), "gc connection") || strings.Contains(err.Error(), "DOLT_GC") {
        log.Warnf("shutdown GC failed (server still shut down): %v", err)
        return nil // treat GC failure as non-fatal to shutdown
    }
    return err
}

Prevention

When it happens

Trigger: runShutdownGC fails: the server is Running but the SQL connection cannot be opened/acquired (server already wedged, wrong DSN/TLS settings), or the CALL DOLT_GC / DOLT_STATS_GC statements error (e.g. GC fails due to table corruption or insufficient privileges).

Common situations: Server half-dead so connections time out during shutdown; GC blocked by long-running transactions; dolt version where DOLT_STATS_GC doesn't exist; ctx passed to Stop already cancelled/expired.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d00e9514f9bf6125. Report an issue: GitHub.