{"record":{"id":"e0f23187fb301162","repo":"gastownhall/beads","slug":"failed-to-commit-pending-changes-before-sync-w","errorCode":null,"errorMessage":"failed to commit pending changes before sync: %w","messagePattern":"failed to commit pending changes before sync: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/federation.go","lineNumber":357,"sourceCode":"// 2. Merge peer's changes (handling conflicts per strategy)\n// 3. Push local changes to peer\n//\n// Returns the sync result including any conflicts encountered.\nfunc (s *DoltStore) Sync(ctx context.Context, peer string, strategy string) (*SyncResult, error) {\n\tresult := &SyncResult{\n\t\tPeer:      peer,\n\t\tStartTime: time.Now(),\n\t}\n\n\t// GH#2474: match PullFrom — commit pending changes before the merge,\n\t// INCLUDING config (where kv.memory.* rows live). Plain Commit excludes\n\t// config (GH#2455), so federation metadata writes such as add-peer plus any\n\t// persistent memories would otherwise leave the working set dirty and wedge\n\t// DOLT_MERGE (\"cannot merge with uncommitted changes\").\n\tif !s.readOnly {\n\t\tif err := s.commitBeforePull(ctx, \"auto-commit before sync\"); err != nil {\n\t\t\tif !isDoltNothingToCommit(err) {\n\t\t\t\tresult.Error = fmt.Errorf(\"failed to commit pending changes before sync: %w\", err)\n\t\t\t\treturn result, result.Error\n\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)","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/federation.go#L339-L375","documentation":"Before pulling, Sync auto-commits any dirty working-set changes (e.g. federation metadata like add-peer plus persistent memories, which plain Commit excludes per GH#2455) so DOLT_MERGE cannot wedge with 'cannot merge with uncommitted changes'. This error means that pre-sync commit itself failed for a reason other than 'nothing to commit'.","triggerScenarios":"Sync(ctx, peer, ...) on a writable store calls commitBeforePull(ctx, \"auto-commit before sync\") and receives a real commit error (SQL failure, lock contention, hook failure) that is not isDoltNothingToCommit.","commonSituations":"Another process holds the dolt working set or server lock; dirty state from a prior crashed sync; disk-full or DB connection drop mid-commit; concurrent syncs racing on the same database.","solutions":["Inspect the wrapped cause to see why the commit failed","Check for and clear stale dolt locks or concurrent `bd sync` processes (ps / dolt_admin status)","Run the sync again after resolving contention — the auto-commit retriggers","If a prior crashed sync left the working set wedged, inspect `dolt status` and commit or discard changes manually","Ensure the dolt sql-server is healthy and the database directory is writable/non-full"],"exampleFix":"// before: blind retry loop\nfor { store.Sync(ctx, peer, \"\", nil) }\n// after: single-flight sync guard\nsyncMu.Lock()\ndefer syncMu.Unlock()\n_, err := store.Sync(ctx, peer, \"\", nil) // auto-commit no longer races","handlingStrategy":"validation","validationCode":"// ensure clean, uncontended working set before Sync\nif anotherSyncRunning() { return ErrSyncBusy }\n_ = store.Commit(ctx, \"pre-sync checkpoint\") // best-effort commit outside readOnly","typeGuard":null,"tryCatchPattern":"result, err := store.Sync(ctx, peer, strategy, opts)\nif err != nil && strings.Contains(err.Error(), \"commit pending changes before sync\") {\n    // clear contention, then retry once\n    releaseLocks(); retrySync()\n}","preventionTips":["Single-flight all syncs with a mutex or lock file","Always commit or checkpoint before invoking Sync","Keep disk space and dolt server health monitored","After a crash, inspect `dolt status` before resuming syncs"],"tags":["dolt","federation","sync","commit"],"backgroundTag":"uncommitted-changes-block-merge","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}