{"record":{"id":"d00e9514f9bf6125","repo":"gastownhall/beads","slug":"server-doltserver-stop-w","errorCode":null,"errorMessage":"server: DoltServer.Stop: %w","messagePattern":"server: DoltServer\\.Stop: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/dbproxy/server/doltserver.go","lineNumber":351,"sourceCode":"\n\t\tif time.Now().After(deadline) {\n\t\t\treturn fmt.Errorf(\"listener not ready after %s: %w\", startReadyTimeout, err)\n\t\t}\n\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-s.egCtx.Done():\n\t\t\treturn errors.New(\"dolt sql-server exited before listener became ready\")\n\t\tcase <-time.After(startReadyPollInterval):\n\t\t}\n\t}\n}\n\nfunc (s *DoltServer) Stop(ctx context.Context) error {\n\tgcErr := s.runShutdownGC(ctx)\n\tif gcErr != nil {\n\t\tgcErr = fmt.Errorf(\"server: DoltServer.Stop: %w\", gcErr)\n\t}\n\n\tif s.cancel != nil {\n\t\ts.cancel()\n\t}\n\tvar waitErr error\n\tif s.eg != nil {\n\t\twaitErr = s.eg.Wait()\n\t\tvar exitErr *exec.ExitError\n\t\tif errors.As(waitErr, &exitErr) || errors.Is(waitErr, context.Canceled) {\n\t\t\twaitErr = nil\n\t\t}\n\t}\n\tif waitErr != nil {\n\t\twaitErr = fmt.Errorf(\"server: DoltServer.Stop: %w\", waitErr)\n\t}\n\tvar closeErr error\n\tif s.logFile != nil {","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/server/doltserver.go#L333-L369","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check whether the error is connection-level — if the server is already dead, this is benign and the shutdown still completed.","Retry Stop with a fresh, non-cancelled context so GC connections can be established.","Run `CALL DOLT_GC()` manually via a SQL client to see the underlying GC error.","Ensure no long-running queries/transactions are holding back GC before calling Stop."],"exampleFix":"// before\nctx, cancel := context.WithCancel(ctx) // already-cancelled ctx starves shutdown GC\ncancel()\n_ = srv.Stop(ctx)\n// after\ngcCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\nif err := srv.Stop(gcCtx); err != nil {\n    log.Warnf(\"stop returned errors: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// Only pass a live context to Stop; a cancelled ctx starves shutdown GC.\nif ctx.Err() != nil {\n    ctx = context.Background()\n}","typeGuard":null,"tryCatchPattern":"if err := srv.Stop(gcCtx); err != nil {\n    if strings.Contains(err.Error(), \"gc connection\") || strings.Contains(err.Error(), \"DOLT_GC\") {\n        log.Warnf(\"shutdown GC failed (server still shut down): %v\", err)\n        return nil // treat GC failure as non-fatal to shutdown\n    }\n    return err\n}","preventionTips":["Call Stop with a fresh context, not one derived from an already-cancelled request scope.","Let long queries finish before stopping to avoid GC blocking.","Verify the dolt version supports DOLT_STATS_GC.","Treat Stop's joined errors individually — GC failure does not mean the server failed to stop."],"tags":["shutdown","garbage-collection","database"],"backgroundTag":"shutdown-gc-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}