gastownhall/beads · error
merge failed: %w
Error message
merge failed: %w
What it means
Sync wraps a failure of Merge(ctx, "<peer>/<branch>") at Step 3. The fetch succeeded but merging the peer's branch into the local branch errored outright — not a conflict outcome, a hard merge failure. The working set may be left mid-merge depending on where the merge failed.
Source
Thrown at internal/storage/dolt/federation.go:377
}
}
}
// Step 1: Fetch from peer
if err := s.Fetch(ctx, peer); err != nil {
result.Error = fmt.Errorf("fetch failed: %w", err)
return result, result.Error
}
result.Fetched = true
// Step 2: Get status before merge
beforeCommit, _ := s.GetCurrentCommit(ctx) // Best effort: empty commit hash means diff won't be logged
// Step 3: Merge peer's branch
remoteBranch := fmt.Sprintf("%s/%s", peer, s.branch)
conflicts, err := s.Merge(ctx, remoteBranch)
if err != nil {
result.Error = fmt.Errorf("merge failed: %w", err)
return result, result.Error
}
// Step 4: Handle conflicts if any
if len(conflicts) > 0 {
result.Conflicts = conflicts
if strategy == "" {
// No strategy specified, leave conflicts for manual resolution
result.Error = fmt.Errorf("merge conflicts require resolution (use --strategy ours|theirs)")
return result, result.Error
}
// Auto-resolve using strategy
for _, c := range conflicts {
if err := s.ResolveConflicts(ctx, c.Field, strategy); err != nil {
result.Error = fmt.Errorf("conflict resolution failed for %s: %w", c.Field, err)
return result, result.ErrorView on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause; check `dolt status` for a wedged merge and abort or complete it
- Commit or stash local changes before syncing so the merge starts clean
- If history diverged, decide ours/theirs strategy up front or fetch+merge manually
- For schema/FK divergence, reconcile rows (delete-vs-insert) before retrying
- Verify the remote branch ref exists locally after fetch (`dolt branch -r`)
Example fix
// before: sync into possibly-dirty working set
store.Sync(ctx, peer, "", nil)
// after: ensure clean state first
if err := store.Commit(ctx, "checkpoint"); err != nil && !isNothingToCommit(err) {
return err
}
store.Sync(ctx, peer, "", nil) Defensive patterns
Strategy: validation
Validate before calling
// commit any dirty state so merge starts clean
if err := store.Commit(ctx, "pre-sync"); err != nil && !isNothingToCommit(err) {
return err
} Type guard
func isHardMergeFailure(err error) bool {
return err != nil && strings.HasPrefix(err.Error(), "merge failed:")
} Try / catch
result, err := store.Sync(ctx, peer, "", opts)
if isHardMergeFailure(err) {
// inspect and unwedge working set before retry
abortOrCompletePendingMerge(); return err
} Prevention
- Sync frequently so histories stay fast-forwardable
- Never force-push on peer branches used for federation
- Keep schema_migrations in lockstep across replicas
- Verify remote branch refs exist after fetch
When it happens
Trigger: Sync Step 3 where s.Merge(ctx, remoteBranch) errors: non-fast-forward with divergent history that cannot auto-merge, uncommitted changes present, schema merge failure (e.g. FK delete-vs-insert divergence that rolls the merge back), or the remote branch missing locally after fetch.
Common situations: Both replicas rewrote history (force-push on peer); mixed-vintage schema_migrations rows (per code comments); merge attempted while the working set is dirty; peer branch deleted upstream so the merged ref doesn't exist.
Related errors
- failed to commit pending changes before pull: %w
- failed to commit pending changes before sync: %w
- fetch failed: %w
- merge conflicts require resolution (use --strategy ours|thei
- conflict resolution failed for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/8797e019a1265aa5.
Report an issue: GitHub.