gastownhall/beads · error

merge succeeded but is_blocked recompute failed: %w

Error message

merge succeeded but is_blocked recompute failed: %w

What it means

After a merge completes with zero conflicts, the store recomputes the denormalized is_blocked column (recomputeBlockedAfterPull). This error signals the merge itself succeeded but the post-merge recompute failed. It's deliberately distinct from the merge error so the developer knows branch state was updated but derived blocked-status data is now stale and needs a recompute.

Source

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

	// bd-578h9.11: like every pull path, a branch merge brings in writes that
	// bypassed the local is_blocked hooks; recompute after a conflict-free
	// merge. Conflicted merges defer to the caller's post-resolution hook
	// (Sync, bd vc merge --strategy) — recomputing over unresolved rows would
	// read garbage.
	preHead := ""
	if !s.readOnly {
		if h, err := s.GetCurrentCommit(ctx); err == nil {
			preHead = h
		}
	}

	conflicts, err := versioncontrolops.Merge(ctx, s.db, branch, s.commitAuthorString())
	if len(conflicts) > 0 {
		span.SetAttributes(attribute.Int("dolt.conflicts", len(conflicts)))
	}
	if err == nil && len(conflicts) == 0 && !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, err
}

// MergeWithStrategy implements storage.StrategicMerger for `bd vc merge
// --strategy` (#4992). Merge (above) runs the bare CALL DOLT_MERGE on the
// shared pool: that is enough to detect a conflict-shaped autocommit
// rejection, but not to resolve one, because Dolt's conflict-tolerant session
// flags (@@dolt_allow_commit_conflicts, @@dolt_force_transaction_commit) are
// session state and the pool may hand a later statement a different
// connection. MergeWithStrategy instead pins a single connection — the same
// pattern Branch/Checkout use for stored procedures — for the whole
// merge/resolve/repair/commit sequence versioncontrolops.MergeWithStrategy
// runs.
//
// A resolved merge (conflicted or clean) always commits, so — unlike Merge,
// which skips the recompute for a still-conflicted merge — the is_blocked

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the recompute manually (RecomputeBlockedAfterMerge / bd equivalent) — merge state is fine, only derived data is stale.
  2. Retry with a fresh, longer-lived context so the recompute isn't cut off.
  3. Ensure the connection pool has capacity for the recompute's own connection.
  4. Verify the issues schema is migrated (is_blocked column present).
  5. Wrap follow-up merge calls so is_blocked staleness is detected and repaired on next run.
Defensive patterns

Strategy: try-catch

Validate before calling

if store.IsReadOnly() { skip recompute } // recompute only runs when !s.readOnly
if err := ctx.Err(); err != nil { /* use a fresh ctx for the recompute */ }

Try / catch

conflicts, err := store.Merge(ctx, branch)
var recomputeErr *fmt.WrapError // or inspect message prefix
if err != nil && strings.Contains(err.Error(), "is_blocked recompute failed") {
    log.Warn("merge succeeded; recompute is_blocked and retry", "err", err)
    _ = store.RecomputeBlockedAfterMerge(ctx)
}

Prevention

When it happens

Trigger: Merge with no conflicts on a writable (non-read-only) store, where recomputeBlockedAfterPull returns an error — its internal transaction/queries fail due to context cancellation, connection starvation, or schema issues with the issues table's is_blocked column.

Common situations: MaxOpenConns:1 pools where the recompute cannot get a connection; long merges that let the ctx expire before recompute; older databases missing columns the recompute expects.

Related errors


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