{"record":{"id":"21bd384dadab3e61","repo":"gastownhall/beads","slug":"acquire-connection-for-remote-ref-prune-w","errorCode":null,"errorMessage":"acquire connection for remote-ref prune: %w","messagePattern":"acquire connection for remote-ref prune: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/store.go","lineNumber":2893,"sourceCode":"\tconn, err := s.db.Conn(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"acquire connection for gc: %w\", err)\n\t}\n\tdefer conn.Close()\n\treturn versioncontrolops.DoltGC(ctx, conn)\n}\n\n// ListRemoteRefs returns the names of all cached remote-tracking refs.\nfunc (s *DoltStore) ListRemoteRefs(ctx context.Context) ([]string, error) {\n\treturn versioncontrolops.ListRemoteRefs(ctx, s.db)\n}\n\n// PruneRemoteRefs deletes all cached remote-tracking refs so a post-squash GC\n// can reclaim the history they anchor (bd-agctw). Returns the deleted names.\nfunc (s *DoltStore) PruneRemoteRefs(ctx context.Context) ([]string, error) {\n\tconn, err := s.db.Conn(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"acquire connection for remote-ref prune: %w\", err)\n\t}\n\tdefer conn.Close()\n\treturn versioncontrolops.PruneRemoteRefs(ctx, conn)\n}\n\n// ListTags returns the names of all Dolt tags.\nfunc (s *DoltStore) ListTags(ctx context.Context) ([]string, error) {\n\treturn versioncontrolops.ListTags(ctx, s.db)\n}\n\n// Flatten squashes all Dolt commit history into a single commit.\n// Pins a single connection because the stored procedures (DOLT_CHECKOUT,\n// DOLT_RESET, etc.) rely on session-scoped state that would be lost if\n// steps execute on different pooled connections.\nfunc (s *DoltStore) Flatten(ctx context.Context) error {\n\tconn, err := s.db.Conn(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"acquire connection for flatten: %w\", err)","sourceCodeStart":2875,"sourceCodeEnd":2911,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/store.go#L2875-L2911","documentation":"PruneRemoteRefs pins a single connection before delegating to versioncontrolops.PruneRemoteRefs (used after squash so GC can reclaim anchored history); this error wraps db.Conn(ctx) failing to hand out that connection. No refs have been pruned; it is a pool-acquisition failure.","triggerScenarios":"Calling PruneRemoteRefs(ctx) when the pool cannot supply a connection: ctx deadline/cancel while waiting, pool saturated with busy connections, server down so dialing a new pooled connection fails, driver ErrBadConn.","commonSituations":"Post-squash maintenance run while the app is under load; shutdown hook with a canceled context; Dolt server outage; stale pool after server restart.","solutions":["Retry PruneRemoteRefs after load subsides; schedule remote-ref pruning in maintenance windows","Raise the ctx timeout for the call","Verify the Dolt server is reachable and the pool is healthy (PingContext) before pruning","Check wrapped error class: dial failure → connectivity/DSN; deadline → timeout/pool saturation"],"exampleFix":"// before\ndeleted, err := store.PruneRemoteRefs(ctx)\n// after\npCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\ndeleted, err := store.PruneRemoteRefs(pCtx)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) { /* connectivity path */ }\n}","handlingStrategy":"retry","validationCode":"// verify server reachability before pruning refs\nif err := s.db.PingContext(ctx); err != nil {\n    return nil, fmt.Errorf(\"skip remote-ref prune, server unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: backoff-retry transient acquisition errors\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, driver.ErrBadConn) {\n        // safe to retry: no refs were pruned\n        return retryPrune(ctx)\n    }\n    return nil, err\n}","preventionTips":["Schedule post-squash pruning as a low-traffic maintenance task","Use a dedicated generous context for prune operations","Verify pool health (PingContext) before prune runs","Keep pool headroom (avoid MaxOpenConns=workload size) for maintenance ops"],"tags":["go","database","connection-pool","dolt"],"backgroundTag":"connection-acquisition-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}