{"record":{"id":"a0975fab27272aac","repo":"gastownhall/beads","slug":"count-blocked-issues-w","errorCode":null,"errorMessage":"count blocked issues: %w","messagePattern":"count blocked issues: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/statistics.go","lineNumber":53,"sourceCode":"}\n\n// GetStatisticsInTx computes the full summary statistics (counts + blocked + ready)\n// in one transaction, using only the normal issues table — no version-control state —\n// so it is portable across every SQL backend. Behaviorally identical to the Dolt and\n// embedded-Dolt implementations: ScanIssueCountsInTx for the status counts, a direct\n// blocked count (the is_blocked flag is maintained in-tx by the shared layer), then\n// ReadyIssues = OpenIssues - BlockedIssues clamped at zero.\nfunc GetStatisticsInTx(ctx context.Context, tx DBTX) (*types.Statistics, error) {\n\tstats := &types.Statistics{}\n\tif err := ScanIssueCountsInTx(ctx, tx, stats); err != nil {\n\t\treturn nil, err\n\t}\n\tvar blocked int\n\tif err := tx.QueryRowContext(ctx, `\n\t\tSELECT COUNT(*) FROM issues\n\t\tWHERE is_blocked = 1 AND status <> 'closed' AND status <> 'pinned'\n\t`).Scan(&blocked); err != nil {\n\t\treturn nil, fmt.Errorf(\"count blocked issues: %w\", err)\n\t}\n\tstats.BlockedIssues = &blocked\n\tready := stats.OpenIssues - blocked\n\tif ready < 0 {\n\t\tready = 0\n\t}\n\tstats.ReadyIssues = &ready\n\treturn stats, nil\n}\n","sourceCodeStart":35,"sourceCodeEnd":63,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/statistics.go#L35-L63","documentation":"GetStatisticsInTx counts blocked non-closed/non-pinned issues with a QueryRowContext().Scan(&blocked) and wraps any failure with this message. Like 3803, this is a single-row aggregate scan failing due to a broken connection, missing table/column, or cancelled context. The is_blocked column must exist and be maintained by the shared layer.","triggerScenarios":"The issues table lacks the is_blocked column (older schema); the tx/connection failed between the counts query and this one; context deadline exceeded; the underlying database rejected the SELECT syntax.","commonSituations":"Running a newer beads binary against a database created by an older version (pre-is_blocked schema); server connection dropped mid-GetStatisticsInTx; DB under heavy load timing out the stats call.","solutions":["Check the wrapped error for 'unknown column is_blocked' and run schema migrations to the current version.","Retry statistics with a fresh transaction if the connection dropped mid-call.","Verify the Dolt server is healthy and the ctx timeout accommodates the blocked-count scan.","If using an embedded backend, confirm the database file was opened read-write so migrations can apply."],"exampleFix":"// before\nstats, err := GetStatisticsInTx(ctx, tx) // unknown column is_blocked\n// after\nif err := store.Migrate(ctx); err != nil { return err } // add is_blocked column\nstats, err := GetStatisticsInTx(ctx, tx)","handlingStrategy":"validation","validationCode":"// confirm the is_blocked column exists before computing statistics\nrows, err := tx.QueryContext(ctx, `SHOW COLUMNS FROM issues LIKE 'is_blocked'`)\nif err != nil || !rows.Next() { return fmt.Errorf(\"schema out of date; run migrations\") }","typeGuard":null,"tryCatchPattern":"stats, err := issueops.GetStatisticsInTx(ctx, tx)\nif err != nil && strings.Contains(err.Error(), \"count blocked issues\") {\n    return fmt.Errorf(\"blocked-count failed (schema/connection): %w\", err)\n}","preventionTips":["Run beads' migration step after every version upgrade","Keep the embedded database file writable so migrations apply","Verify server health before long stats pipelines","Read the wrapped inner error — it names the exact SQL failure"],"tags":["go","sql","schema","statistics"],"backgroundTag":"schema-column-missing","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}