{"record":{"id":"963315d82dc26546","repo":"gastownhall/beads","slug":"failed-to-commit-conflict-resolution-w","errorCode":null,"errorMessage":"failed to commit conflict resolution: %w","messagePattern":"failed to commit conflict resolution: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/federation.go","lineNumber":406,"sourceCode":"\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\n\t\t\t}\n\t\t}\n\t\tresult.ConflictsResolved = true\n\n\t\t// Commit the resolution INCLUDING config: the operator chose this\n\t\t// strategy, and plain Commit excludes config (GH#2455). A config-only\n\t\t// conflict — routine now that kv.memory.* memories sync through config —\n\t\t// would otherwise resolve but never commit, leaving the merge\n\t\t// unconcluded and re-wedging the next sync.\n\t\tif err := s.CommitMergeResolution(ctx, fmt.Sprintf(\"Resolve conflicts from %s using %s strategy\", peer, strategy)); err != nil {\n\t\t\tresult.Error = fmt.Errorf(\"failed to commit conflict resolution: %w\", err)\n\t\t\treturn result, result.Error\n\t\t}\n\n\t\t// bd-578h9.11: the conflicted merge skipped the automatic is_blocked\n\t\t// recompute (unresolved rows would have fed it garbage); now that the\n\t\t// resolution is committed, cover the whole merge+resolution window.\n\t\tif err := s.RecomputeBlockedAfterMerge(ctx, beforeCommit); err != nil {\n\t\t\tresult.Error = fmt.Errorf(\"conflicts resolved but is_blocked recompute failed: %w\", err)\n\t\t\treturn result, result.Error\n\t\t}\n\t}\n\tresult.Merged = true\n\n\t// Count pulled commits\n\tafterCommit, _ := s.GetCurrentCommit(ctx) // Best effort: empty commit hash means diff won't be logged\n\tif beforeCommit != afterCommit {\n\t\tresult.PulledCommits = 1 // Simplified - could count actual commits\n\t}","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/federation.go#L388-L424","documentation":"After auto-resolving conflicts, Sync must commit the resolution with CommitMergeResolution (which includes config changes; plain Commit excludes them per GH#2455). If that commit fails, the merge stays unconcluded, the working set stays dirty, and the next sync would re-wedge. The error wraps the commit cause.","triggerScenarios":"store.Sync with a strategy where all ResolveConflicts calls succeed but CommitMergeResolution(ctx, msg) errors — SQL failure, lock contention, disk full, or a concurrent writer dirtying the working set between resolution and commit.","commonSituations":"Long conflict-resolution windows during which another process wrote changes; dolt server connection dropped; read-only filesystem; two syncs racing so the second invalidates the first's merge state.","solutions":["Inspect the wrapped commit error and `dolt status` to see remaining working-set state","Re-run sync: the code path re-enters, re-commits any pending changes (commitBeforePull), and completes the resolution commit","Serialize syncs (single-flight lock) to prevent concurrent writers from dirtying the tree","Check dolt server health, disk space, and connection stability","If wedged, manually commit the resolution (`dolt add -A && dolt commit`) then re-sync"],"exampleFix":"// before: parallel agents syncing\n// after: serialize\nvar syncMu sync.Mutex\nfunc safeSync(s *storage.DoltStore, peer string) error {\n    syncMu.Lock(); defer syncMu.Unlock()\n    _, err := s.Sync(context.Background(), peer, \"theirs\", nil)\n    return err\n}","handlingStrategy":"validation","validationCode":"// pre-check: writable store, no concurrent sync\nif store == nil || isReadOnly() || syncInFlight() {\n    return ErrSyncBusy\n}","typeGuard":null,"tryCatchPattern":"result, err := store.Sync(ctx, peer, strategy, opts)\nif err != nil && strings.Contains(err.Error(), \"failed to commit conflict resolution\") {\n    // working set may be wedged; inspect and re-sync\n    inspectDoltStatus(); retrySync(strategy)\n}","preventionTips":["Single-flight syncs to avoid writers dirtying the tree mid-resolution","Monitor disk space and dolt server connection stability","After failures, always check `dolt status` before the next operation"],"tags":["dolt","federation","sync","commit","conflict"],"backgroundTag":"uncommitted-changes-block-merge","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}