{"record":{"id":"1951c63340888b7e","repo":"gastownhall/beads","slug":"fetch-failed-w-1951c6","errorCode":null,"errorMessage":"fetch failed: %w","messagePattern":"fetch failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/embeddeddolt/federation.go","lineNumber":311,"sourceCode":"\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)\n\t\treturn result, result.Error\n\t}\n\n\t// Step 4: Handle conflicts\n\tif len(conflicts) > 0 {\n\t\tresult.Conflicts = conflicts","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/federation.go#L293-L329","documentation":"Sync fetches the peer remote before merging. Any failure from store.Fetch(ctx, peer) — network unreachable, unknown remote, bad refspec, or Dolt fetch internals — is wrapped as 'fetch failed'. result.Fetched stays false, so the sync aborted before any merge work.","triggerScenarios":"store.Sync(ctx, peer) where s.Fetch(ctx, peer) errors: the peer remote is not configured, the peer is offline/unreachable, SSH/HTTPS credentials are missing or expired, or the peer repo path is wrong.","commonSituations":"Peer machine is down during federation sync; remote URL typo in peer configuration; expired credentials/token; firewall blocking the transport; peer branch was force-removed.","solutions":["Verify the peer remote is registered and reachable (`dolt remote -v`, ping the host).","Check/refresh credentials for the remote transport (SSH keys, tokens).","Retry sync once connectivity is restored — fetch is safe to retry.","Correct the peer name/URL configuration and re-run sync."],"exampleFix":"// before: peer offline -> fetch failed\nresult, err := store.Sync(ctx, \"laptop\")\n// after: probe reachability first\nif err := checkPeerReachable(\"laptop\"); err != nil {\n    return fmt.Errorf(\"defer sync: peer unreachable: %w\", err)\n}\nresult, err = store.Sync(ctx, \"laptop\")","handlingStrategy":"retry","validationCode":"// probe the peer before syncing\nfunc peerReachable(peer string) error {\n    conn, err := net.DialTimeout(\"tcp\", peerHost(peer), 5*time.Second)\n    if err != nil { return err }\n    return conn.Close()\n}","typeGuard":null,"tryCatchPattern":"result, err := store.Sync(ctx, peer)\nif err != nil && strings.Contains(err.Error(), \"fetch failed\") {\n    // fetch is idempotent: back off and retry\n    time.Sleep(backoff)\n    result, err = store.Sync(ctx, peer)\n}","preventionTips":["Register and verify peer remotes before scheduling syncs.","Refresh SSH keys/tokens before expiry.","Health-check peers before federation jobs.","Use bounded retries with backoff for transient network faults."],"tags":["network","fetch","sync","dolt"],"backgroundTag":"git-fetch-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}