gastownhall/beads · critical
pull from %s/%s reported success but merged nothing into %s:
Error message
pull from %s/%s reported success but merged nothing into %s: %s is at %s while %s is at %s (their common ancestor is %s), so the commits on the remote-tracking ref are not on the branch this database reads. Most often another client pushed after this pull fetched and a re-run will merge it; if the divergence survives repeated re-runs, the transport is not landing merges on this branch (for example the dolt CLI directory and the sql-server are serving different databases or branches)
What it means
This store verifies that a pull actually merged the fetched commits into the branch the database reads (via DOLT_MERGE_BASE containment against the refreshed remote-tracking ref). This error fires when the transport reported success but the local branch does not contain the tracking ref — i.e., the merge landed nowhere the caller reads. It names both tips and their merge base so the developer can diagnose divergence.
Source
Thrown at internal/storage/dolt/store.go:4187
// nothing", so a caller that surfaces it reads the same diagnosis.
// - otherwise: local and the tracking ref have genuinely diverged (their
// common ancestor is neither tip), which no re-pull can fast-forward away.
// That is the stuck-transport / split-brain signal, and it stays a hard
// error.
//
// The split fails safe: a true divergence can never be demoted to the
// retryable class, because its common ancestor is by definition neither tip.
// Distinguishing the benign race from a genuinely failed transport would
// still need the remote tip as of the transport's own fetch, which git-backed
// remotes never write into this database; the merge base is the best post-hoc
// split available. Classified before the display fallback below rewrites an
// empty localHash.
behindFastForwardable := localHash != "" && mergeBase.String == localHash
if localHash == "" {
localHash = "unknown"
}
mergedNothing := fmt.Errorf("pull from %s/%s reported success but merged nothing into %s: %s is at %s while %s is at %s "+
"(their common ancestor is %s), so the commits on the remote-tracking ref are not on the branch this "+
"database reads. Most often another client pushed after this pull fetched and a re-run will merge it; "+
"if the divergence survives repeated re-runs, the transport is not landing merges on this branch "+
"(for example the dolt CLI directory and the sql-server are serving different databases or branches)",
remote, s.branch, s.branch, s.branch, localHash, trackingRef, remoteHash, mergeBase.String)
if behindFastForwardable {
return fmt.Errorf("%w: %w", versioncontrolops.ErrPullBehindFastForwardable, mergedNothing)
}
return mergedNothing
}
// refreshTrackingRef fetches remote/s.branch into this database's
// remote-tracking refs over a dedicated long-timeout, credential-aware
// connection, so verifyPullLanded's comparison reads a tracking ref this
// database just wrote. It mirrors pullTransport's own network calls: a
// long-timeout connection (openLongTimeoutConn) wrapped in the remote's
// credential/S3 environment (withRemoteOperationEnv), which is what lets the
// refresh reach CLI-routed (git-protocol, credential, cloud-auth) remotes thatView on GitHub (pinned to 71377f2769)
Solutions
- Re-run the pull — if it was a push race, the next pull fast-forwards and the error disappears.
- If it persists, confirm the dolt CLI working directory and the sql-server are serving the same database and branch as this store's connection string.
- Compare the hashes in the message (branch tip vs tracking ref vs merge base) to see whether the branch is an ancestor (retryable) or diverged.
- Restart the sql-server so cached git-blobstore mirrors re-sync if the remote is git-backed.
- Inspect `dolt branch -a` / dolt_remote_branches in the actual database this store connects to.
Example fix
// before
// persistent failure: CLI in /srv/bd, sql-server serving /var/lib/dolt/bd
// after
// point both at the same database dir, or configure the store to use the
// sql-server's own DSN exclusively:
store, err := OpenDoltStore("dolt://user@tcp(localhost:3307)/bd?branch=main") Defensive patterns
Strategy: retry
Validate before calling
// before pulling, confirm CLI dir and sql-server serve the same db/branch: // dolt branch --current (in the CLI workdir) vs store's configured branch
Try / catch
if err := store.Pull(ctx); err != nil {
var mergedNothingErr *fmt.wrapError // or match on message
if strings.Contains(err.Error(), "reported success but merged nothing") &&
!errors.Is(err, versioncontrolops.ErrPullBehindFastForwardable) {
// genuine divergence: reconfigure transports / restart sql-server before retrying
}
return err
} Prevention
- Run the dolt CLI and sql-server against the same database directory and branch.
- Prefer one transport (CLI or SQL) consistently for a given store.
- Wait >1s between a peer's push and your pull on git-blobstore remotes.
- Monitor the hash triple in the message; persistent identical hashes mean a stuck transport, not a race.
When it happens
Trigger: The pull transport (dolt CLI subprocess or CALL DOLT_PULL on a sql-server) operated against a different database/branch/directory than the one this store reads; or a peer pushed to the remote after this pull fetched, leaving the branch strictly behind (that variant is wrapped in ErrPullBehindFastForwardable, error 2703).
Common situations: The dolt CLI runs in one working directory while the sql-server serves another database or branch (split-brain config); another clone pushed mid-pull; a git-blobstore-backed remote inside its 1s read-sync TTL window; PullRemote targeting a federation peer whose merge lands on a default branch instead of s.branch.
Related errors
- pull from %s: %w
- database not available: %w
- no active beads workspace
- failed to persist sync.remote to config.yaml: %w
- failed to set sync remote: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b44c513eb6770400.
Report an issue: GitHub.