{"record":{"id":"b44c513eb6770400","repo":"gastownhall/beads","slug":"pull-from-s-s-reported-success-but-merged-nothin","errorCode":null,"errorMessage":"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)","messagePattern":"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\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/storage/dolt/store.go","lineNumber":4187,"sourceCode":"\t//     nothing\", so a caller that surfaces it reads the same diagnosis.\n\t//   - otherwise: local and the tracking ref have genuinely diverged (their\n\t//     common ancestor is neither tip), which no re-pull can fast-forward away.\n\t//     That is the stuck-transport / split-brain signal, and it stays a hard\n\t//     error.\n\t//\n\t// The split fails safe: a true divergence can never be demoted to the\n\t// retryable class, because its common ancestor is by definition neither tip.\n\t// Distinguishing the benign race from a genuinely failed transport would\n\t// still need the remote tip as of the transport's own fetch, which git-backed\n\t// remotes never write into this database; the merge base is the best post-hoc\n\t// split available. Classified before the display fallback below rewrites an\n\t// empty localHash.\n\tbehindFastForwardable := localHash != \"\" && mergeBase.String == localHash\n\n\tif localHash == \"\" {\n\t\tlocalHash = \"unknown\"\n\t}\n\tmergedNothing := fmt.Errorf(\"pull from %s/%s reported success but merged nothing into %s: %s is at %s while %s is at %s \"+\n\t\t\"(their common ancestor is %s), so the commits on the remote-tracking ref are not on the branch this \"+\n\t\t\"database reads. Most often another client pushed after this pull fetched and a re-run will merge it; \"+\n\t\t\"if the divergence survives repeated re-runs, the transport is not landing merges on this branch \"+\n\t\t\"(for example the dolt CLI directory and the sql-server are serving different databases or branches)\",\n\t\tremote, s.branch, s.branch, s.branch, localHash, trackingRef, remoteHash, mergeBase.String)\n\tif behindFastForwardable {\n\t\treturn fmt.Errorf(\"%w: %w\", versioncontrolops.ErrPullBehindFastForwardable, mergedNothing)\n\t}\n\treturn mergedNothing\n}\n\n// refreshTrackingRef fetches remote/s.branch into this database's\n// remote-tracking refs over a dedicated long-timeout, credential-aware\n// connection, so verifyPullLanded's comparison reads a tracking ref this\n// database just wrote. It mirrors pullTransport's own network calls: a\n// long-timeout connection (openLongTimeoutConn) wrapped in the remote's\n// credential/S3 environment (withRemoteOperationEnv), which is what lets the\n// refresh reach CLI-routed (git-protocol, credential, cloud-auth) remotes that","sourceCodeStart":4169,"sourceCodeEnd":4205,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/store.go#L4169-L4205","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\n// persistent failure: CLI in /srv/bd, sql-server serving /var/lib/dolt/bd\n// after\n// point both at the same database dir, or configure the store to use the\n// sql-server's own DSN exclusively:\nstore, err := OpenDoltStore(\"dolt://user@tcp(localhost:3307)/bd?branch=main\")","handlingStrategy":"retry","validationCode":"// before pulling, confirm CLI dir and sql-server serve the same db/branch:\n// dolt branch --current  (in the CLI workdir)  vs  store's configured branch","typeGuard":null,"tryCatchPattern":"if err := store.Pull(ctx); err != nil {\n    var mergedNothingErr *fmt.wrapError // or match on message\n    if strings.Contains(err.Error(), \"reported success but merged nothing\") &&\n        !errors.Is(err, versioncontrolops.ErrPullBehindFastForwardable) {\n        // genuine divergence: reconfigure transports / restart sql-server before retrying\n    }\n    return err\n}","preventionTips":["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."],"tags":["dolt","pull","sync","split-brain","divergence"],"backgroundTag":"pull-merged-nothing","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}