gastownhall/beads · warning

conflict for %s %s was not cleared (no conflict row deleted)

Error message

conflict for %s %s was not cleared (no conflict row deleted)

What it means

After issuing the DELETE on dolt_conflicts_<table>, this fires when RowsAffected reports 0 — the conflict row asked for no longer exists. Rather than reporting success for a conflict it did not actually clear, the code aborts so the caller knows the resolution was a no-op.

Source

Thrown at internal/storage/versioncontrolops/conflicts.go:435

		// only when the row really is gone.
		if n, err := res.RowsAffected(); err != nil || n == 0 {
			present, err := conflictTargetStillPresent(ctx, db, table, keyCol, ourKey)
			if err != nil {
				return fmt.Errorf("confirm %s %s still exists after writing their values: %w", table, key, err)
			}
			if !present {
				return fmt.Errorf("their values for %s %s matched no row (was it deleted concurrently?); conflict left unresolved", table, key)
			}
		}
	}

	del := fmt.Sprintf("DELETE FROM `dolt_conflicts_%s` WHERE `our_%s` = ?", table, keyCol) //nolint:gosec // identifiers validated
	res, err := db.ExecContext(ctx, del, ourKey)
	if err != nil {
		return fmt.Errorf("clear conflict for %s %s: %w", table, key, err)
	}
	if n, err := res.RowsAffected(); err == nil && n == 0 {
		return fmt.Errorf("conflict for %s %s was not cleared (no conflict row deleted)", table, key)
	}
	return nil
}

// GetMergeBlockers reports the merge state that `bd conflicts` cannot show as
// rows: whether a merge is open at all, plus the schema conflicts and
// constraint violations that make dolt refuse the merge commit even when
// every dolt_conflicts row is resolved (wy-36ilm F12). Without it, that state
// surfaced only as a raw dolt error from CommitMergeResolution, after the
// operator had been told "0 conflicts remain".
//
// Each source is read independently and a MISSING source table is not an
// error: dolt_schema_conflicts and dolt_constraint_violations are dolt system
// tables whose presence has varied across versions, and a diagnosis helper
// must never be the thing that fails the command.
func GetMergeBlockers(ctx context.Context, db DBConn) (storage.MergeBlockers, error) {
	var out storage.MergeBlockers
	var errs []error

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-query dolt_conflicts_<table> for the current conflict set; the row is already resolved, so treat this as success and continue.
  2. Run resolution to completion in one pass without interleaving other resolution invocations on the same branch.
  3. If the conflict reappeared (merge restarted), re-run the merge/pull to refresh the conflict table and resolve the new rows.
  4. Deduplicate concurrent resolvers (single session/lock) so only one process deletes conflict rows.

Example fix

// before: resolving keys captured long ago
err := ops.ResolveConflictRows(ctx, db, "issues", "theirs", staleKeys)
// after: refresh the conflict set first
rows := listCurrentConflicts(ctx, db, "issues") // SELECT our_id FROM dolt_conflicts_issues
err = ops.ResolveConflictRows(ctx, db, "issues", "theirs", keysOf(rows))
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the conflict row still exists before resolving:
var n int
_ = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts_issues WHERE our_id = ?", key).Scan(&n)
if n == 0 { return nil } // nothing to resolve

Try / catch

if err := ops.ResolveConflictRows(ctx, db, table, "theirs", keys); err != nil {
  if strings.Contains(err.Error(), "was not cleared") {
    return nil // already resolved by someone else; treat as success
  }
  return err
}

Prevention

When it happens

Trigger: Resolving a conflict row that was already deleted: another session resolved the same conflict concurrently, a whole-table strategy was applied elsewhere, or the key passed to ResolveConflictRows is stale (the conflict set changed since the key was read).

Common situations: Two operators or two automation runs resolving the same merge simultaneously; resolving keys obtained from an earlier listing after a rebase/merge changed state; replaying a resolution script twice.

Related errors


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