{"record":{"id":"61f54a231e0e4269","repo":"gastownhall/beads","slug":"recompute-blocked-w","errorCode":null,"errorMessage":"recompute-blocked: %w","messagePattern":"recompute-blocked: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/sync.go","lineNumber":328,"sourceCode":"\t\t\t// through to the hard error below.\n\t\t\tif isPullBehindFastForwardableErr(pullErr) {\n\t\t\t\tout.Transients = append(out.Transients, syncTransient{\n\t\t\t\t\tAttempt: attempt, Kind: syncTransientPullBehind, Error: pullErr.Error(),\n\t\t\t\t})\n\t\t\t\tops.report(\"pull behind a fast-forwardable remote tip (peer pushed after our fetch) — re-pulling and retrying\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn out, fmt.Errorf(\"pull: %w\", pullErr)\n\t\t}\n\t\tif conflictErr != nil {\n\t\t\treturn out, fmt.Errorf(\"conflict check: %w\", conflictErr)\n\t\t}\n\n\t\tops.report(\"recompute-blocked\")\n\t\tcorrected, err := ops.recompute(ctx)\n\t\tif err != nil {\n\t\t\tif !isRecomputeDirtyGraphErr(err) {\n\t\t\t\treturn out, fmt.Errorf(\"recompute-blocked: %w\", err)\n\t\t\t}\n\t\t\t// Not our failure and not a durable one: someone else's\n\t\t\t// uncommitted edit to issues/dependencies landed between our pull\n\t\t\t// and our repair. Treat it exactly like a push race — re-enter the\n\t\t\t// attempt loop, and if the budget runs out report the transient\n\t\t\t// exit so the next tick tries again. Classifying it as a hard\n\t\t\t// error instead left local commits unpublished until a tick\n\t\t\t// happened to catch a clean working set, which on a shared\n\t\t\t// sql-server topology is luck (wy-mlnz2).\n\t\t\t//\n\t\t\t// Two things about the retry are worth knowing before touching it.\n\t\t\t// It is paced by the pull's round trip, not by a sleep — the loop\n\t\t\t// has none. And the retry does not merely WAIT for the other\n\t\t\t// writer: the pull's own pre-merge auto-commit (GH#2474) stages and\n\t\t\t// commits whatever is dirty, so it is often what clears the guard,\n\t\t\t// committing that writer's already-SQL-committed rows under this\n\t\t\t// sync's author. That is pre-existing behavior on attempt 1 of\n\t\t\t// every tick and is data-safe, but a retry repeats the exposure —","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/sync.go#L310-L346","documentation":"ops.recompute failed with an error that is not a 'dirty graph' race. Dirty-graph errors (another process's uncommitted edit between pull and repair) are retried as transients; all other recompute failures abort the sync loop as hard errors.","triggerScenarios":"The graph-repair/recompute step hits a real failure: corrupted dependency graph rows, storage write error, constraint violation during repair, or context cancellation.","commonSituations":"Manually edited issues.jsonl or DB rows leaving the dependency graph inconsistent; disk-full during recompute; bug in a migration that produced edges pointing at nonexistent issues.","solutions":["Read the wrapped error to find which graph invariant failed","Fix or remove the offending dependency/issue rows (bd dep remove / bd doctor)","Restore the DB from .beads/issues.jsonl export or git history if the graph is corrupted","Retry sync after ensuring no other bd process holds the DB"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate the dependency graph before syncing\nfor _, edge := range allDeps {\n    if !issueExists(edge.IssueID) || !issueExists(edge.DependsOnID) {\n        return fmt.Errorf(\"dangling dependency %s -> %s; repair before sync\", edge.IssueID, edge.DependsOnID)\n    }\n}","typeGuard":null,"tryCatchPattern":"out, err := runSyncCommand(ctx, opts)\nif err != nil {\n    var recErr *RecomputeError\n    if errors.As(err, &recErr) && !isDirtyGraphErr(recErr) {\n        // hard failure: inspect graph corruption, run bd doctor\n    }\n    return err\n}","preventionTips":["Don't hand-edit DB rows or issues.jsonl while bd is running","Run `bd doctor` after manual edits or interrupted migrations","Ensure adequate disk space for recompute writes","Check that no other process holds uncommitted edits during sync"],"tags":["go","sync","data-integrity"],"backgroundTag":"graph-recompute-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}