{"record":{"id":"d6aba72460e765dd","repo":"gastownhall/beads","slug":"failed-to-begin-transaction-w","errorCode":null,"errorMessage":"failed to begin transaction: %w","messagePattern":"failed to begin transaction: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/fix/blocked.go","lineNumber":53,"sourceCode":"\t\treturn nil\n\t}\n\tdefer db.Close()\n\n\tif skip, err := guardFixTarget(\"Blocked-state fix\", db, beadsDir, cfg); skip {\n\t\treturn err\n\t}\n\n\treturn repairBlockedState(context.Background(), db)\n}\n\n// repairBlockedState recomputes is_blocked on an open connection. Split from\n// RecomputeBlocked so the repair is testable against an existing store handle.\nfunc repairBlockedState(ctx context.Context, db *sql.DB) error {\n\t// Explicit transaction so writes persist when @@autocommit is OFF (e.g. a\n\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)","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/fix/blocked.go#L35-L71","documentation":"repairBlockedState starts an explicit SQL transaction before recomputing is_blocked, so writes persist even on a Dolt server running with --no-auto-commit. This error wraps the failure of db.Begin() itself — the transaction could not be opened at all, so no repair work was attempted. It most commonly indicates the connection to the Dolt SQL server is broken, closed, or refused.","triggerScenarios":"Calling fix.RecomputeBlocked(path) (which calls repairBlockedState) when db.Begin() on the open *sql.DB fails: the Dolt server connection is dead or timed out, the server rejected the session (e.g. after a restart), the connection pool returned an unusable connection, or the driver failed to issue BEGIN against the server.","commonSituations":"Dolt server was restarted or crashed between openDoltDB and the repair; network/keepalive timeout dropped an idle pooled connection; server max-connections exhausted; running against a misconfigured port so the 'connection' is not actually a Dolt SQL server.","solutions":["Rerun `bd doctor --fix` — this is often a transient dead-connection failure and a fresh openDoltDB connection will succeed.","Verify the Dolt SQL server is running and reachable (check the server config in .beads and the port); restart it if needed.","Check server logs for max_connections exhaustion or auth/session errors and raise limits or fix credentials as needed.","If the Dolt server runs with restrictive settings, ensure it supports transactional BEGIN (standard `dolt sql-server` does; a proxy or read-only replica may not)."],"exampleFix":"// before (server went away mid-run)\nerr: failed to begin transaction: driver: bad connection\n\n// after: retry with a fresh handle\nif err := repairBlockedState(ctx, db); err != nil {\n\tdb.Close()\n\tdb, cfg, err = openDoltDB(beadsDir)\n\tif err == nil {\n\t\terr = repairBlockedState(ctx, db)\n\t}\n}","handlingStrategy":"retry","validationCode":"// Probe the connection before the repair\nif err := db.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"dolt server unreachable, restart it before doctor --fix: %w\", err)\n}","typeGuard":"func isOpenDB(db *sql.DB) bool {\n\tctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)\n\tdefer cancel()\n\treturn db.PingContext(ctx) == nil\n}","tryCatchPattern":"if err := repairBlockedState(ctx, db); err != nil && strings.Contains(err.Error(), \"failed to begin transaction\") {\n\t// connection was dead — reopen and retry once\n\tdb.Close()\n\tdb, _, err = openDoltDB(beadsDir)\n\tif err == nil {\n\t\terr = repairBlockedState(ctx, db)\n\t}\n}","preventionTips":["Keep the Dolt sql-server running and healthy for the whole doctor --fix run","Run doctor --fix against a local server to avoid network idle timeouts","Watch server logs for max-connections or session-kill events","Retry transient begin failures once with a fresh connection before giving up"],"tags":["go","database","dolt","sql","transaction"],"backgroundTag":"transaction-begin-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}