{"record":{"id":"36ee88604558e233","repo":"gastownhall/beads","slug":"commit-pending-before-sync-w","errorCode":null,"errorMessage":"commit pending before sync: %w","messagePattern":"commit pending before sync: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/embeddeddolt/federation.go","lineNumber":305,"sourceCode":"\n// Sync performs a full bidirectional sync with a peer:\n// 1. Fetch from peer\n// 2. Merge peer's changes (handling conflicts per strategy)\n// 3. Push local changes to peer\nfunc (s *EmbeddedDoltStore) Sync(ctx context.Context, peer string, strategy string) (*storage.SyncResult, error) {\n\tresult := &storage.SyncResult{\n\t\tPeer:      peer,\n\t\tStartTime: time.Now(),\n\t}\n\n\t// GH#2474 / bd-578h9.2: commit pending changes before the merge, matching\n\t// embedded Pull/PullRemote/PullFrom and server-mode Sync. Embedded Commit is\n\t// DOLT_COMMIT('-Am'), so it stages config — where kv.memory.* memories live —\n\t// and a leftover dirty working set (e.g. a `bd remember` write) would\n\t// otherwise make DOLT_MERGE refuse to start (\"cannot merge with uncommitted\n\t// changes\"). CommitPending is a no-op when the working set is already clean.\n\tif _, err := s.CommitPending(ctx, \"beads\"); err != nil {\n\t\tresult.Error = fmt.Errorf(\"commit pending before sync: %w\", err)\n\t\treturn result, result.Error\n\t}\n\n\t// Step 1: Fetch\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 commit before merge for change detection\n\tbeforeCommit, _ := s.GetCurrentCommit(ctx)\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)","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/federation.go#L287-L323","documentation":"Sync wraps any failure from CommitPending with this message before attempting the peer fetch/merge. EmbeddedDolt.Commit runs DOLT_COMMIT('-Am'), and a dirty working set (e.g. an uncommitted `bd remember` write to kv.memory.*) would make DOLT_MERGE refuse to start with 'cannot merge with uncommitted changes'. CommitPending is a no-op when the working set is already clean, so this error means the auto-commit of pending local writes itself failed.","triggerScenarios":"Calling store.Sync(ctx, peer) when CommitPending(ctx, \"beads\") returns an error — e.g. the underlying DOLT_COMMIT('-Am') invocation fails due to a corrupted working set, a lock file left by a crashed process, or a storage I/O failure.","commonSituations":"A previous bd process crashed leaving dolt lock files; disk full during the auto-commit; a concurrent writer holds the working set; leftover uncommitted changes from a `bd remember` write that Dolt cannot commit.","solutions":["Run `bd doctor` or inspect the repo's dolt status to find and clear stale lock files, then retry sync.","Commit or discard the dirty working set manually (dolt status / dolt checkout -- .) and re-run sync.","Check disk space and filesystem permissions on the embedded Dolt data directory.","If corruption is suspected, restore from a backup/clone of the repo and re-sync."],"exampleFix":"// before: sync fails because a stale lock blocks the auto-commit\nresult, err := store.Sync(ctx, peer)\n// after: ensure clean state first\nif err := store.CommitPending(ctx, \"beads\"); err != nil {\n    // clean stale dolt lock files / resolve dirty working set, then retry\n    return err\n}\nresult, err = store.Sync(ctx, peer)","handlingStrategy":"try-catch","validationCode":"// pre-check working set state if the API exposes it\nif cleaner, ok := store.(interface{ IsClean(ctx context.Context) (bool, error) }); ok {\n    clean, err := cleaner.IsClean(ctx)\n    if err != nil { return err }\n    if !clean {\n        if err := store.CommitPending(ctx, \"beads\"); err != nil {\n            return fmt.Errorf(\"cannot sync: pending commit failed: %w\", err)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"result, err := store.Sync(ctx, peer)\nif err != nil && strings.Contains(err.Error(), \"commit pending before sync\") {\n    // inspect dolt status/locks, clear stale state, then retry once\n    if rerr := recoverWorkingSet(); rerr == nil {\n        result, err = store.Sync(ctx, peer)\n    }\n}","preventionTips":["Always let bd auto-commit pending writes before manual dolt operations.","Monitor for stale dolt lock files after crashes.","Ensure adequate disk space on the data directory.","Avoid concurrent writers to the same embedded repo during sync."],"tags":["dolt","sync","working-set"],"backgroundTag":"uncommitted-changes-block-merge","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}