gastownhall/beads · warning

release merge connection: %w

Error message

release merge connection: %w

What it means

After a successful merge with a pinned connection, the code closes that connection before running the recompute so it doesn't starve a constrained pool. This error wraps a failure of that conn.Close() call. The merge succeeded and results are valid; only returning the connection to the pool failed, which is unusual (driver-level close error).

Source

Thrown at internal/storage/dolt/store.go:4933

	conn, err := s.db.Conn(ctx)
	if err != nil {
		return nil, fmt.Errorf("acquire connection for merge: %w", err)
	}
	conflicts, err = versioncontrolops.MergeWithStrategy(ctx, conn, branch, s.commitAuthorString(), strategy)
	// Release the pinned connection before the recompute: s.db's pool can be
	// configured with a single connection (setupTestStore's MaxOpenConns: 1
	// mirrors constrained production configs), and recomputeBlockedAfterPull
	// acquires its own connection — held past this point, conn would starve
	// it of the only one available.
	closeErr := conn.Close()
	if len(conflicts) > 0 {
		span.SetAttributes(attribute.Int("dolt.conflicts", len(conflicts)))
	}
	if err != nil {
		return conflicts, err
	}
	if closeErr != nil {
		return conflicts, fmt.Errorf("release merge connection: %w", closeErr)
	}
	if !s.readOnly {
		if rerr := s.recomputeBlockedAfterPull(ctx, preHead); rerr != nil {
			return conflicts, fmt.Errorf("merge succeeded but is_blocked recompute failed: %w", rerr)
		}
	}
	return conflicts, nil
}

// RecomputeBlockedAfterMerge recomputes the denormalized is_blocked column
// for the rows changed since fromCommit and commits the result — the hook a
// caller that resolved merge conflicts itself must run after committing the
// resolution (bd-578h9.11): conflicted merges skip the automatic recompute
// because unresolved rows would feed it garbage, and nothing else covers the
// merged-in writes. fromCommit is the pre-merge HEAD; empty degrades to a
// full-graph recompute.
func (s *DoltStore) RecomputeBlockedAfterMerge(ctx context.Context, fromCommit string) error {
	return s.recomputeBlockedAfterPull(ctx, fromCommit)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Treat the merge as successful — verify conflicts/results and continue; the pool will discard the bad connection.
  2. Ping or validate pool health; database/sql removes dead connections automatically on subsequent use.
  3. Check Dolt server logs for session drops/timeouts during merges.
  4. If this recurs, upgrade the Dolt driver or raise conn max lifetime to recycle sessions proactively.
  5. Retry the operation if subsequent recompute also failed.

Example fix

// before
if closeErr != nil { return conflicts, fmt.Errorf("release merge connection: %w", closeErr) }
// after
if closeErr != nil {
    log.Warn("merge connection close failed; pool will recycle", "err", closeErr)
} // don't fail the successful merge on a pool-release error
Defensive patterns

Strategy: try-catch

Try / catch

conflicts, closeErr := store.MergeWithStrategy(ctx, branch, strategy)
if closeErr != nil {
    // merge succeeded; pool release failed — log and continue, don't fail results
    log.Warn("merge ok but connection release failed", "err", closeErr)
}
if len(conflicts) > 0 { handleConflicts(conflicts) }

Prevention

When it happens

Trigger: MergeWithStrategy succeeded, then the deferred/explicit conn.Close() returned a non-nil error — typically a broken underlying connection (server closed it mid-merge lifecycle) or driver close failure.

Common situations: Dolt server restarted or dropped the session after the merge completed; network interruption; driver bugs on connections that experienced protocol errors.

Related errors


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