gastownhall/beads · error
begin is_blocked recompute: %w
Error message
begin is_blocked recompute: %w
What it means
Wraps a failure of db.BeginTx when starting the transaction for the full is_blocked recompute. Every recompute reads and writes inside a single transaction so the dirty-graph guard and recompute see the same working set; if the transaction cannot begin, the recompute aborts before doing any work.
Source
Thrown at internal/storage/dolt/store.go:4589
}
defer conn.Close()
if err := s.pinStoreBranch(ctx, conn); err != nil {
return 0, err
}
return s.recomputeAllBlockedWithDB(ctx, conn)
}
// txBeginner is satisfied by both *sql.DB and *sql.Conn, letting
// recomputeAllBlockedWithDB run either against a caller-owned pinned
// *sql.Conn (recomputeAllBlocked) or directly against a *sql.DB (tests).
type txBeginner interface {
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
}
func (s *DoltStore) recomputeAllBlockedWithDB(ctx context.Context, db txBeginner) (int, error) {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return 0, fmt.Errorf("begin is_blocked recompute: %w", err)
}
// One shared body across every mode (guard a dirty graph, then recompute):
// the guard refuses to derive and commit is_blocked from uncommitted
// issue/dependency edits, and it runs inside THIS tx so it sees exactly the
// working set the recompute reads (bd-6dnrw.37).
changed, err := versioncontrolops.GuardedRecomputeAllBlockedInTx(ctx, tx)
if err != nil {
_ = tx.Rollback()
return 0, err
}
if err := s.commitSQLTx(ctx, "commit is_blocked recompute", tx); err != nil {
return 0, err
}
if changed > 0 {
// Stage only issues — the synced table is_blocked lives on (wisps are
// dolt_ignore'd) — so an unrelated dirty working set is not swept in.
if err := s.doltAddAndCommit(ctx, blockedRecomputeStagedTableList(),
versioncontrolops.BlockedRecomputeCommitMsg); err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Retry the recompute — a fresh connection will be acquired
- Check the wrapped cause for context cancellation and increase the timeout
- Verify Dolt server is up and accepting connections
- If ErrBadConn recurs, confirm the server's idle timeout is not shorter than bd's long-timeout setting
Defensive patterns
Strategy: retry
Validate before calling
// Ensure the connection is alive before beginning work
if err := conn.PingContext(ctx); err != nil {
// re-acquire the connection; the old one is bad
} Try / catch
if err := store.RecomputeAllBlocked(ctx); err != nil {
if strings.Contains(err.Error(), "begin is_blocked recompute") {
// transient: retry once with a fresh connection
time.Sleep(time.Second)
err = store.RecomputeAllBlocked(ctx)
}
return err
} Prevention
- Set server wait_timeout longer than bd's long-timeout window
- Start the transaction promptly after acquiring the connection
- Avoid context deadlines shorter than the recompute duration
When it happens
Trigger: BeginTx returns an error on the pinned long-timeout connection — the underlying connection went bad (driver.ErrBadConn), the context was canceled before the transaction started, or the Dolt server rejected the new transaction (e.g. shutdown or too many connections).
Common situations: Connection sat idle past server wait_timeout and was dropped; Dolt server restart between acquiring the connection and beginning the tx; context deadline exceeded.
Related errors
- begin tx: %w
- federation filter: begin staged is_blocked recompute: %w
- begin read tx: %w
- begin write tx: %w
- ErrTransaction
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/95a848fc74502009.
Report an issue: GitHub.