{"record":{"id":"e5299a7a6c4b42e4","repo":"gastownhall/beads","slug":"failed-to-recompute-is-blocked-w","errorCode":null,"errorMessage":"failed to recompute is_blocked: %w","messagePattern":"failed to recompute is_blocked: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/fix/blocked.go","lineNumber":68,"sourceCode":"\t// Dolt server started with --no-auto-commit).\n\ttx, err := db.Begin()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to begin transaction: %w\", err)\n\t}\n\t// Refuse to derive and commit is_blocked from a dirty graph: like the store\n\t// paths, the recompute reads the working set and stages only `issues`, so a\n\t// dirty issues/dependencies tree would taint the repair commit (bd-6dnrw.37).\n\t// In a `bd doctor --fix` run the dependency-graph fixes commit ahead of this\n\t// one, so the tree is normally clean here; when it is not, surface it as an\n\t// actionable error rather than committing tainted state.\n\tif err := issueops.GuardBlockedRecomputeWorkingSet(ctx, tx); err != nil {\n\t\t_ = tx.Rollback()\n\t\treturn err\n\t}\n\tchanged, err := issueops.RecomputeAllIsBlockedInTx(ctx, tx)\n\tif err != nil {\n\t\t_ = tx.Rollback()\n\t\treturn fmt.Errorf(\"failed to recompute is_blocked: %w\", err)\n\t}\n\tif err := tx.Commit(); err != nil {\n\t\treturn fmt.Errorf(\"failed to commit is_blocked repairs: %w\", err)\n\t}\n\n\tif changed == 0 {\n\t\tfmt.Println(\"  is_blocked already consistent — nothing to fix\")\n\t\treturn nil\n\t}\n\n\t// Persist the corrected flags as a Dolt commit, staging only issues — the\n\t// synced table is_blocked lives on (wisps are dolt_ignore'd). This path keeps\n\t// its own fresh-DB lifecycle rather than the shared store helper, but it must\n\t// not report success on a failed commit: a swallowed DOLT_COMMIT error would\n\t// leave the repair in the working set only, silently undone by the next pull.\n\t// bd doctor is server-mode only, so the server supplies the commit identity.\n\tif _, err := db.ExecContext(ctx, \"CALL DOLT_ADD(?)\", \"issues\"); err != nil {\n\t\treturn fmt.Errorf(\"failed to stage is_blocked repairs: %w\", err)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/fix/blocked.go#L50-L86","documentation":"After opening a transaction and confirming the issues/dependencies working set is clean, repairBlockedState calls issueops.RecomputeAllIsBlockedInTx to derive is_blocked for every issue and wisp inside that transaction. This error wraps any failure of that recompute and the transaction is rolled back, so the store is left untouched. It signals the recompute SQL failed — a schema/query/server problem, not a data-consistency problem.","triggerScenarios":"Calling fix.RecomputeBlocked (via repairBlockedState) when RecomputeAllIsBlockedInTx returns an error: malformed or missing issues/dependencies tables in the Dolt database, a SQL error during the UPDATE/JOIN recompute (e.g. column is_blocked missing after a version mismatch), query timeout, or the connection dropped mid-transaction.","commonSituations":"A database created by an older beads version lacking the is_blocked column; a corrupted or partially-migrated Dolt database; server killed mid-query (OOM, timeout); a schema migration that ran halfway.","solutions":["Read the wrapped %w cause from the error output — it names the underlying SQL/driver failure; fix that first.","Verify the database schema matches the current beads version (is_blocked column exists on issues and the wisps table); run any pending `bd` migrations or upgrade.","Test the Dolt database health (`bd doctor` non-fix checks or dolt sql -q \"select count(*) from issues\") to spot corruption; restore from backup or re-init and re-pull if corrupted.","Rerun `bd doctor --fix` after addressing the cause — the rollback guarantees no partial is_blocked writes were persisted."],"exampleFix":"// before (old DB missing is_blocked)\nerr: failed to recompute is_blocked: Error 1054: Unknown column 'is_blocked' in 'issues'\n\n// after: upgrade/migrate the DB first, then retry\nif err := repairBlockedState(ctx, db); err != nil {\n\tlog.Printf(\"recompute failed: %v — check schema version\", err)\n\t// run `bd migrate` / upgrade, then retry the fix\n}","handlingStrategy":"try-catch","validationCode":"// Confirm schema before recomputing\nrows, err := db.Query(\"SHOW COLUMNS FROM issues LIKE 'is_blocked'\")\nif err != nil || !rows.Next() {\n\tlog.Fatal(\"issues.is_blocked column missing — run bd migrations/upgrade first\")\n}","typeGuard":"func schemaHasIsBlocked(ctx context.Context, db *sql.DB) bool {\n\tvar col string\n\terr := db.QueryRowContext(ctx,\n\t\t\"SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='issues' AND COLUMN_NAME='is_blocked'\").Scan(&col)\n\treturn err == nil\n}","tryCatchPattern":"if err := repairBlockedState(ctx, db); err != nil {\n\tvar cause error\n\tif errors.As(err, &cause) {\n\t\tlog.Printf(\"is_blocked recompute failed (tx rolled back, store unchanged): %v\", cause)\n\t}\n\t// no partial writes: safe to fix schema/corruption and retry\n}","preventionTips":["Keep the beads CLI and database schema versions in sync — upgrade/migrate before running fixes","Run bd doctor (non-fix) to catch schema/corruption issues before --fix","Monitor Dolt server memory/timeout limits for large databases","Rely on the rollback: recompute failures never leave partial is_blocked writes"],"tags":["go","database","dolt","sql","schema"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}