gastownhall/beads · error
acquire gc connection: %w
Error message
acquire gc connection: %w
What it means
After opening the GC connection, runShutdownGC grabs a physical connection with db.Conn(ctx). This error means no connection could be acquired before the context deadline or the server refused/failed the connection attempt.
Source
Thrown at internal/storage/dbproxy/server/doltserver.go:399
if rmErr != nil {
rmErr = fmt.Errorf("server: DoltServer.Stop: remove pidfile: %w", rmErr)
}
return errors.Join(gcErr, waitErr, closeErr, rmErr)
}
func (s *DoltServer) runShutdownGC(ctx context.Context) (retErr error) {
if s.database == "" || !s.Running(ctx) {
return nil
}
db, err := sql.Open("mysql", s.DSN(ctx, s.database, "root", ""))
if err != nil {
return fmt.Errorf("open gc connection: %w", err)
}
defer func() { retErr = errors.Join(retErr, db.Close()) }()
conn, err := db.Conn(ctx)
if err != nil {
return fmt.Errorf("acquire gc connection: %w", err)
}
defer func() { retErr = errors.Join(retErr, conn.Close()) }()
if err := versioncontrolops.DoltGC(ctx, conn); err != nil {
retErr = errors.Join(retErr, err)
}
if _, err := conn.ExecContext(ctx, "CALL DOLT_STATS_GC()"); err != nil {
retErr = errors.Join(retErr, fmt.Errorf("dolt_stats_gc: %w", err))
}
return retErr
}
func (s *DoltServer) Running(_ context.Context) bool {
if s.egCtx == nil {
return false
}
return s.egCtx.Err() == nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Increase the Stop/stopWithTimeout timeout so the context is not cancelled during GC
- Check server logs for 'too many connections' or refusal at shutdown; ensure Stop runs before the underlying server process is killed
- Verify no other caller holds all connections; close leaked connections elsewhere in the app
- Retry once after a short delay if the error is context-deadline related and the server is still Running
Example fix
// before ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() err := server.Stop(ctx) // after ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // allow GC to connect defer cancel() err := server.Stop(ctx)
Defensive patterns
Strategy: retry
Validate before calling
// before Stop, confirm server still accepting connections
if !server.Running(ctx) {
return nil // nothing to GC
} Try / catch
err := server.Stop(ctx)
if err != nil && strings.Contains(err.Error(), "acquire gc connection") {
// give the server a moment, retry once with fresh context
retryCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err = server.Stop(retryCtx)
} Prevention
- Use a shutdown timeout large enough for GC (tens of seconds, not 1-2s)
- Avoid calling Stop concurrently from multiple goroutines
- Monitor connection-pool usage so external load can't starve the GC connection
When it happens
Trigger: DoltServer.Stop during shutdown GC when the server has already stopped accepting connections (race between Stop and server teardown), the context is cancelled/timed out (stopWithTimeout deadline), or max connections are exhausted.
Common situations: Shutdown timeout too short so ctx is done before db.Conn completes; Stop called twice concurrently so the second run races the dying server; external load maxing out Dolt's connection limit.
Related errors
- ensure global db: failed to open connection: %w
- flush: server not reachable: %w
- timeout (%s) waiting for spawn marker %s; wait for the in-pr
- open gc connection: %w
- errIdleTimeout
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d5b55e26d02770a3.
Report an issue: GitHub.