gastownhall/beads · error

failed to recompute is_blocked: %w

Error message

failed to recompute is_blocked: %w

What it means

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.

Source

Thrown at cmd/bd/doctor/fix/blocked.go:68

	// Dolt server started with --no-auto-commit).
	tx, err := db.Begin()
	if err != nil {
		return fmt.Errorf("failed to begin transaction: %w", err)
	}
	// Refuse to derive and commit is_blocked from a dirty graph: like the store
	// paths, the recompute reads the working set and stages only `issues`, so a
	// dirty issues/dependencies tree would taint the repair commit (bd-6dnrw.37).
	// In a `bd doctor --fix` run the dependency-graph fixes commit ahead of this
	// one, so the tree is normally clean here; when it is not, surface it as an
	// actionable error rather than committing tainted state.
	if err := issueops.GuardBlockedRecomputeWorkingSet(ctx, tx); err != nil {
		_ = tx.Rollback()
		return err
	}
	changed, err := issueops.RecomputeAllIsBlockedInTx(ctx, tx)
	if err != nil {
		_ = tx.Rollback()
		return fmt.Errorf("failed to recompute is_blocked: %w", err)
	}
	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit is_blocked repairs: %w", err)
	}

	if changed == 0 {
		fmt.Println("  is_blocked already consistent — nothing to fix")
		return nil
	}

	// Persist the corrected flags as a Dolt commit, staging only issues — the
	// synced table is_blocked lives on (wisps are dolt_ignore'd). This path keeps
	// its own fresh-DB lifecycle rather than the shared store helper, but it must
	// not report success on a failed commit: a swallowed DOLT_COMMIT error would
	// leave the repair in the working set only, silently undone by the next pull.
	// bd doctor is server-mode only, so the server supplies the commit identity.
	if _, err := db.ExecContext(ctx, "CALL DOLT_ADD(?)", "issues"); err != nil {
		return fmt.Errorf("failed to stage is_blocked repairs: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped %w cause from the error output — it names the underlying SQL/driver failure; fix that first.
  2. 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.
  3. 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.
  4. Rerun `bd doctor --fix` after addressing the cause — the rollback guarantees no partial is_blocked writes were persisted.

Example fix

// before (old DB missing is_blocked)
err: failed to recompute is_blocked: Error 1054: Unknown column 'is_blocked' in 'issues'

// after: upgrade/migrate the DB first, then retry
if err := repairBlockedState(ctx, db); err != nil {
	log.Printf("recompute failed: %v — check schema version", err)
	// run `bd migrate` / upgrade, then retry the fix
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm schema before recomputing
rows, err := db.Query("SHOW COLUMNS FROM issues LIKE 'is_blocked'")
if err != nil || !rows.Next() {
	log.Fatal("issues.is_blocked column missing — run bd migrations/upgrade first")
}

Type guard

func schemaHasIsBlocked(ctx context.Context, db *sql.DB) bool {
	var col string
	err := db.QueryRowContext(ctx,
		"SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='issues' AND COLUMN_NAME='is_blocked'").Scan(&col)
	return err == nil
}

Try / catch

if err := repairBlockedState(ctx, db); err != nil {
	var cause error
	if errors.As(err, &cause) {
		log.Printf("is_blocked recompute failed (tx rolled back, store unchanged): %v", cause)
	}
	// no partial writes: safe to fix schema/corruption and retry
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/e5299a7a6c4b42e4. Report an issue: GitHub.