gastownhall/beads · error
clear %s conflict: %w
Error message
clear %s conflict: %w
What it means
The DELETE issued against dolt_conflicts_<table> failed at the database level; the underlying driver error is wrapped with this message. This means SQL execution itself failed — connection loss, lock contention, a missing or renamed conflict table, or a schema mismatch — not that zero rows matched.
Source
Thrown at internal/storage/versioncontrolops/automerge.go:716
if _, ok := unionConflictKeyColumns[table]; !ok {
return fmt.Errorf("table %s is not union-mergeable", table)
}
for _, row := range plan {
preds := make([]string, 0, len(row.columns))
args := make([]any, 0, len(row.columns))
for i, k := range row.columns {
v := row.values[i]
if v == nil {
return fmt.Errorf("unexpected %s conflict row with no our_%s (safety check bypassed)", table, k)
}
preds = append(preds, "`our_"+k+"` = ?")
args = append(args, v)
}
//nolint:gosec // table and key columns come from the unionConflictKeyColumns allowlist.
stmt := "DELETE FROM `dolt_conflicts_" + table + "` WHERE " + strings.Join(preds, " AND ")
res, err := db.ExecContext(ctx, stmt, args...)
if err != nil {
return fmt.Errorf("clear %s conflict: %w", table, err)
}
if n, err := res.RowsAffected(); err == nil && n == 0 {
return fmt.Errorf("a %s conflict was not cleared (no conflict row deleted)", table)
}
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped %w cause to identify the SQL error (table missing vs connection vs lock timeout).
- If the conflict table no longer exists, the conflicts were likely already resolved — re-check conflict state before retrying.
- For transient connection/lock errors, retry the whole auto-resolve (re-running the check pass first) rather than resuming mid-plan.
- Ensure only one process at a time performs merge resolution on the repo to avoid concurrent clears.
Example fix
// before — treating every ExecContext failure as fatal without inspecting the cause
if err != nil { return fmt.Errorf("clear %s conflict: %w", table, err) }
// after — retry transient errors once with a fresh check pass
if err != nil {
if errors.Is(err, driver.ErrBadConn) {
return retryAutoResolve(ctx, db, table) // re-runs unionConflictsAreSafe then resolve
}
return fmt.Errorf("clear %s conflict: %w", table, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the conflict table exists before resolving
var n int
if err := db.QueryRowContext(ctx,
"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = ?",
"dolt_conflicts_"+table).Scan(&n); err == nil && n == 0 {
return nil // nothing to resolve
} Try / catch
err := resolveUnionConflicts(ctx, db, table, plan)
if err != nil {
var driverErr *mysqldriver.MySQLError
if errors.As(err, &driverErr) && isTransient(driverErr.Number) {
// rebuild plan and retry once
} else if strings.Contains(err.Error(), "doesn't exist") {
// conflicts already cleared; treat as resolved
} else {
return err
}
} Prevention
- Hold a single-writer lock on the repo during merge resolution.
- Check conflict-table existence before each resolution run.
- Retry the full check+resolve sequence on transient connection errors, not the resolve step alone.
- Monitor connection-pool health for long merges.
When it happens
Trigger: db.ExecContext returns an error while running DELETE FROM `dolt_conflicts_<table>` WHERE our_<keycol> = ? — e.g. the database connection dropped mid-resolution, the conflict table doesn't exist (conflicts already cleared or never created), or a lock/timeout on the table.
Common situations: Another process resolved or cleared conflicts concurrently and dropped the conflict table; the dolt server restarted or the connection pool timed out during a long merge; Dolt returned a lock-wait timeout under concurrent write load.
Related errors
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
- failed to query orphaned dependencies: %w
- row iteration error: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ba32cce38eb07e21.
Report an issue: GitHub.