gastownhall/beads · error

failed to resolve %s conflicts: %w

Error message

failed to resolve %s conflicts: %w

What it means

This error wraps a failure from the Dolt stored procedure CALL DOLT_CONFLICTS_RESOLVE('--theirs', table) inside TryAutoResolveMergeConflicts. The routine resolves merge conflicts for a hardcoded bead table by taking the incoming ('--theirs') version of every conflicted row. If the SQL call errors — bad table name, no active conflict state, or a Dolt engine failure — it is wrapped with the table name so the caller knows which table's conflicts could not be resolved.

Source

Thrown at internal/storage/versioncontrolops/mergesettle.go:560

			}
			if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--theirs', 'config')"); err != nil {
				return false, fmt.Errorf("failed to resolve config conflicts: %w", err)
			}
		case "issues":
			// Field-level three-way merge, not a table-level --ours/--theirs:
			// a cell only one side changed keeps that side's value and only a
			// genuinely contested cell falls to LWW (automerge.go).
			if err := resolveIssuesFieldMerge(ctx, db, issuesPlan); err != nil {
				return false, err
			}
		case "labels", "comments", "events":
			if err := resolveUnionConflicts(ctx, db, table, unionPlans[table]); err != nil {
				return false, err
			}
		default:
			//nolint:gosec // G201: table is one of the hardcoded constants above.
			if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--theirs', '"+table+"')"); err != nil {
				return false, fmt.Errorf("failed to resolve %s conflicts: %w", table, err)
			}
		}
		//nolint:gosec // G201: table is one of the hardcoded constants above.
		if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+table+"')"); err != nil {
			return false, fmt.Errorf("failed to stage %s: %w", table, err)
		}
	}

	return true, nil
}

// CommitResolvedConflicts creates the dolt commit that concludes a merge whose
// conflicts TryAutoResolveMergeConflicts settled. Callers that saw
// resolved=true MUST call this, and only AFTER TryRepairFKCascadeViolations
// has run: DOLT_COMMIT refuses a working set with outstanding constraint
// violations, so a merge carrying both an auto-resolvable conflict and an FK
// cascade violation could never settle while the resolver committed first
// (bd-578h9.14).

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the merge from a clean state: ensure the working set is in a conflicted merge (check dolt_status / dolt_conflicts) before calling SettleMerge.
  2. Verify the Dolt server version supports DOLT_CONFLICTS_RESOLVE with '--theirs' and a table argument; upgrade dolt if the procedure signature changed.
  3. Inspect the wrapped inner error (%w) for the underlying SQL error — it names the real cause (unknown procedure, no conflicts, lock timeout).
  4. Ensure no other process concurrently operates on the same database during merge settlement; serialize SettleMerge calls.

Example fix

// before
if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--theirs', '"+table+"')"); err != nil {
	return false, fmt.Errorf("failed to resolve %s conflicts: %w", table, err)
}
// after
var hasConflicts int
if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts WHERE `table` = ?", table).Scan(&hasConflicts); err != nil || hasConflicts == 0 {
	return false, nil // nothing to resolve; skip instead of failing
}
if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--theirs', '"+table+"')"); err != nil {
	return false, fmt.Errorf("failed to resolve %s conflicts: %w", table, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

var n int
err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts WHERE `table` = ?", table).Scan(&n)
// proceed only if err == nil && n > 0 and dolt_status shows an active merge

Type guard

func hasActiveMergeConflicts(ctx context.Context, db DBConn, table string) bool {
	var n int
	if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts WHERE `table` = ?", table).Scan(&n); err != nil {
		return false
	}
	return n > 0
}

Try / catch

ok, err := TryAutoResolveMergeConflicts(ctx, db)
if err != nil {
	var resolveErr *fmt.WrapError // or errors.As on the wrapped driver error
	if errors.As(err, &resolveErr) && strings.Contains(err.Error(), "failed to resolve") {
		_, _ = db.ExecContext(ctx, "CALL DOLT_MERGE('--abort')") // reset to clean state, then retry SettleMerge
	}
	return err
}

Prevention

When it happens

Trigger: SettleMerge → TryAutoResolveMergeConflicts hits a conflict class that falls into the default branch (not union-resolved) and CALL DOLT_CONFLICTS_RESOLVE('--theirs', '<table>') returns a SQL error, e.g. no conflicts exist for that table, the merge was aborted, or the Dolt procedure rejects the argument.

Common situations: A concurrent process aborted or completed the merge between conflict detection and resolution; a Dolt version where the stored procedure signature changed; corrupted or missing conflict metadata after a crashed merge; calling SettleMerge when the working set is not actually in a conflicted merge state.

Related errors


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