{"record":{"id":"8797e019a1265aa5","repo":"gastownhall/beads","slug":"merge-failed-w","errorCode":null,"errorMessage":"merge failed: %w","messagePattern":"merge failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/federation.go","lineNumber":377,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\n\t// Step 1: Fetch from peer\n\tif err := s.Fetch(ctx, peer); err != nil {\n\t\tresult.Error = fmt.Errorf(\"fetch failed: %w\", err)\n\t\treturn result, result.Error\n\t}\n\tresult.Fetched = true\n\n\t// Step 2: Get status before merge\n\tbeforeCommit, _ := s.GetCurrentCommit(ctx) // Best effort: empty commit hash means diff won't be logged\n\n\t// Step 3: Merge peer's branch\n\tremoteBranch := fmt.Sprintf(\"%s/%s\", peer, s.branch)\n\tconflicts, err := s.Merge(ctx, remoteBranch)\n\tif err != nil {\n\t\tresult.Error = fmt.Errorf(\"merge failed: %w\", err)\n\t\treturn result, result.Error\n\t}\n\n\t// Step 4: Handle conflicts if any\n\tif len(conflicts) > 0 {\n\t\tresult.Conflicts = conflicts\n\n\t\tif strategy == \"\" {\n\t\t\t// No strategy specified, leave conflicts for manual resolution\n\t\t\tresult.Error = fmt.Errorf(\"merge conflicts require resolution (use --strategy ours|theirs)\")\n\t\t\treturn result, result.Error\n\t\t}\n\n\t\t// Auto-resolve using strategy\n\t\tfor _, c := range conflicts {\n\t\t\tif err := s.ResolveConflicts(ctx, c.Field, strategy); err != nil {\n\t\t\t\tresult.Error = fmt.Errorf(\"conflict resolution failed for %s: %w\", c.Field, err)\n\t\t\t\treturn result, result.Error","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/federation.go#L359-L395","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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`)"],"exampleFix":"// before: sync into possibly-dirty working set\nstore.Sync(ctx, peer, \"\", nil)\n// after: ensure clean state first\nif err := store.Commit(ctx, \"checkpoint\"); err != nil && !isNothingToCommit(err) {\n    return err\n}\nstore.Sync(ctx, peer, \"\", nil)","handlingStrategy":"validation","validationCode":"// commit any dirty state so merge starts clean\nif err := store.Commit(ctx, \"pre-sync\"); err != nil && !isNothingToCommit(err) {\n    return err\n}","typeGuard":"func isHardMergeFailure(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"merge failed:\")\n}","tryCatchPattern":"result, err := store.Sync(ctx, peer, \"\", opts)\nif isHardMergeFailure(err) {\n    // inspect and unwedge working set before retry\n    abortOrCompletePendingMerge(); return err\n}","preventionTips":["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"],"tags":["dolt","federation","sync","merge"],"backgroundTag":"merge-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}