gastownhall/beads · error
commit pending before sync: %w
Error message
commit pending before sync: %w
What it means
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.
Source
Thrown at internal/storage/embeddeddolt/federation.go:305
// Sync performs a full bidirectional sync with a peer:
// 1. Fetch from peer
// 2. Merge peer's changes (handling conflicts per strategy)
// 3. Push local changes to peer
func (s *EmbeddedDoltStore) Sync(ctx context.Context, peer string, strategy string) (*storage.SyncResult, error) {
result := &storage.SyncResult{
Peer: peer,
StartTime: time.Now(),
}
// GH#2474 / bd-578h9.2: commit pending changes before the merge, matching
// embedded Pull/PullRemote/PullFrom and server-mode Sync. Embedded Commit is
// DOLT_COMMIT('-Am'), so it stages config — where kv.memory.* memories live —
// and a leftover dirty working set (e.g. a `bd remember` write) would
// otherwise make DOLT_MERGE refuse to start ("cannot merge with uncommitted
// changes"). CommitPending is a no-op when the working set is already clean.
if _, err := s.CommitPending(ctx, "beads"); err != nil {
result.Error = fmt.Errorf("commit pending before sync: %w", err)
return result, result.Error
}
// Step 1: Fetch
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 commit before merge for change detection
beforeCommit, _ := s.GetCurrentCommit(ctx)
// 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)View on GitHub (pinned to 71377f2769)
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.
Example fix
// before: sync fails because a stale lock blocks the auto-commit
result, err := store.Sync(ctx, peer)
// after: ensure clean state first
if err := store.CommitPending(ctx, "beads"); err != nil {
// clean stale dolt lock files / resolve dirty working set, then retry
return err
}
result, err = store.Sync(ctx, peer) Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check working set state if the API exposes it
if cleaner, ok := store.(interface{ IsClean(ctx context.Context) (bool, error) }); ok {
clean, err := cleaner.IsClean(ctx)
if err != nil { return err }
if !clean {
if err := store.CommitPending(ctx, "beads"); err != nil {
return fmt.Errorf("cannot sync: pending commit failed: %w", err)
}
}
} Try / catch
result, err := store.Sync(ctx, peer)
if err != nil && strings.Contains(err.Error(), "commit pending before sync") {
// inspect dolt status/locks, clear stale state, then retry once
if rerr := recoverWorkingSet(); rerr == nil {
result, err = store.Sync(ctx, peer)
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- database not available: %w
- no active beads workspace
- failed to persist sync.remote to config.yaml: %w
- failed to set sync remote: %w
- conflict check: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/36ee88604558e233.
Report an issue: GitHub.