{"record":{"id":"05527517fb198f9c","repo":"gastownhall/beads","slug":"begin-is-blocked-recompute-w-055275","errorCode":null,"errorMessage":"begin is_blocked recompute: %w","messagePattern":"begin is_blocked recompute: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/blocked_recompute.go","lineNumber":73,"sourceCode":"\n// RecomputeAllBlockedOnConn runs the whole full is_blocked repair on conn and\n// returns the number of rows it corrected: guard + recompute inside one\n// transaction, then — only when something actually changed — stage `issues`\n// alone and commit under BlockedRecomputeCommitMsg.\n//\n// author may be empty, which omits --author and lets the server attribute the\n// commit to the connected session. That is the right default for the\n// proxied-server plane, whose every other commit (uow.Tx.Commit) is likewise\n// unauthored; a store that has a configured committer identity passes it.\n//\n// The returned count is meaningful even alongside a non-nil error from the\n// staging step: the rows WERE corrected in the working set, only the history\n// entry failed, and a caller that reported 0 there would be lying about the\n// database it is looking at.\nfunc RecomputeAllBlockedOnConn(ctx context.Context, conn BlockedRecomputeConn, author string) (int64, error) {\n\ttx, err := conn.BeginTx(ctx, nil)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"begin is_blocked recompute: %w\", err)\n\t}\n\tchanged, err := GuardedRecomputeAllBlockedInTx(ctx, tx)\n\tif err != nil {\n\t\t_ = tx.Rollback()\n\t\treturn 0, err\n\t}\n\tif err := tx.Commit(); err != nil {\n\t\treturn 0, fmt.Errorf(\"commit is_blocked recompute: %w\", err)\n\t}\n\tif changed > 0 {\n\t\tif err := StageAndCommit(ctx, conn, BlockedRecomputeStagedTables(), BlockedRecomputeCommitMsg, author); err != nil {\n\t\t\treturn changed, err\n\t\t}\n\t}\n\treturn changed, nil\n}\n","sourceCodeStart":55,"sourceCodeEnd":90,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/blocked_recompute.go#L55-L90","documentation":"RecomputeAllBlockedOnConn opens a transaction for the is_blocked recompute and wraps BeginTx failure as \"begin is_blocked recompute: <cause>\". It throws when the connection cannot start a transaction — the database is closed, the connection is broken, or the driver rejects the isolation level. No recompute work has happened yet, so it is safe to retry.","triggerScenarios":"RecomputeAllBlockedOnConn(ctx, conn, author) when conn.BeginTx fails: connection closed/pooled-broken, database locked by another writer in restrictive drivers, or invalid tx options.","commonSituations":"Calling after db.Close() or during shutdown; connection dropped by a network hiccup or server idle timeout; concurrent long-running writer transactions blocking new ones.","solutions":["Check that the DB connection is open and healthy before calling","Retry with backoff if the cause is a transient connection/lock error","Inspect the wrapped cause for driver-specific lock or close messages","Avoid calling concurrently with operations that hold long write transactions"],"exampleFix":"// before\nn, err := vcops.RecomputeAllBlockedOnConn(ctx, conn, \"agent\")\n// after\nif err := conn.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"db unavailable: %w\", err)\n}\nn, err := vcops.RecomputeAllBlockedOnConn(ctx, conn, \"agent\")\nif err != nil { return fmt.Errorf(\"recompute: %w\", err) }","handlingStrategy":"retry","validationCode":"if err := conn.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"db not ready: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"n, err := vcops.RecomputeAllBlockedOnConn(ctx, conn, author)\nif err != nil {\n\tif strings.Contains(err.Error(), \"begin is_blocked recompute\") && isTransient(errors.Unwrap(err)) {\n\t\treturn retryWithBackoff(3, func() error {\n\t\t\t_, e := vcops.RecomputeAllBlockedOnConn(ctx, conn, author); return e\n\t\t})\n\t}\n\treturn err\n}","preventionTips":["Ping the connection before long recompute jobs","Avoid running during shutdown or while db.Close() may execute","Keep transactions short to reduce lock contention with other writers"],"tags":["transaction","database","dolt"],"backgroundTag":"transaction-begin-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}