{"record":{"id":"f0c9768f63e1f122","repo":"gastownhall/beads","slug":"push-w","errorCode":null,"errorMessage":"push: %w","messagePattern":"push: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/sync.go","lineNumber":398,"sourceCode":"\t\t// exhaustion from inheriting stuck-looking evidence.\n\t\tevidence = dirtyEvidence{}\n\t\tout.RowsCorrected += corrected\n\n\t\t// From here on this run has completed a pull and an is_blocked repair,\n\t\t// so a conflict on a LATER attempt cannot describe itself as a run that\n\t\t// touched nothing.\n\t\tout.Pulled = true\n\n\t\tops.report(\"push\")\n\t\tpushErr := ops.push(ctx)\n\t\tif pushErr == nil {\n\t\t\tout.Status = syncStatusOK\n\t\t\tout.Pushed = true\n\t\t\tout.LastPushError = \"\"\n\t\t\treturn out, nil\n\t\t}\n\t\tif !isPushRaceErr(pushErr) {\n\t\t\treturn out, fmt.Errorf(\"push: %w\", pushErr)\n\t\t}\n\t\t// Another replica pushed between our merge and our push, so the remote\n\t\t// genuinely moved: loop back to pull and pick up its commits. Anything\n\t\t// that is not a fast-forward race cannot converge by retrying and was\n\t\t// returned above.\n\t\tout.LastPushError = pushErr.Error()\n\t\tout.Transients = append(out.Transients, syncTransient{\n\t\t\tAttempt: attempt, Kind: syncTransientPushRace, Error: pushErr.Error(),\n\t\t})\n\t\tops.report(\"push race (non-fast-forward) — re-pulling and retrying\")\n\t}\n\n\tout.Status = syncStatusRetriesExhausted\n\tout.DirtyGraphFingerprint = evidence.fold()\n\treturn out, nil\n}\n\n// dirtyEvidence accumulates one fingerprint per blocked attempt.","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/sync.go#L380-L416","documentation":"The push step of the sync loop failed with an error that is not a push race (remote moved fast-forwardably between merge and push — those retry). All other push errors abort the sync loop.","triggerScenarios":"ops.push returns a non-race error: remote rejects the push (auth, protected refs, non-fast-forward divergence), Dolt push RPC failure, or remote storage unavailable.","commonSituations":"Expired remote credentials; another replica force-pushed divergent history; remote Dolt server read-only or at capacity; firewall/proxy blocking the push endpoint.","solutions":["Read the wrapped pushErr for the concrete rejection reason","Refresh remote credentials/token","Fetch and reconcile with the remote (bd sync pull path or dolt pull) if history diverged non-fast-forwardably","Verify the remote is writable and healthy (server logs, quotas)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify remote is writable and credentials valid before syncing\nif err := checkRemoteWritable(remoteURL); err != nil {\n    return fmt.Errorf(\"remote not writable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"out, err := runSyncCommand(ctx, opts)\nif err != nil {\n    var pushErr *PushError\n    if errors.As(err, &pushErr) && !isPushRaceErr(pushErr.Unwrap()) {\n        // non-race: inspect auth/permission/divergence, fix, then retry\n    }\n    return err\n}","preventionTips":["Keep remote credentials fresh and test with a small push first","Never force-push shared Dolt refs that replicas sync from","Monitor remote server health/quotas before bulk syncs","Re-pull when teammates report pushes so history stays fast-forwardable"],"tags":["go","sync","network","dolt"],"backgroundTag":"dolt-push-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}