gastownhall/beads · error
get blocking info: scan blocked-by: %w
Error message
get blocking info: scan blocked-by: %w
What it means
Returned by queryBlockedByInfo when a row of the blocked-by SELECT (issue_id, depends_on_id, type) cannot be scanned into three strings. Typically caused by NULL or non-string values in any of the three columns of dependencies/wisp_dependencies, or schema drift.
Source
Thrown at internal/storage/issueops/dependency_queries.go:627
SELECT d.issue_id, %s AS depends_on_id, d.type
FROM %s d
WHERE d.issue_id IN (%s) AND d.type IN ('blocks', 'parent-child')
`, depTargetExpr("d"), depTable, inClause)
rows, err := tx.QueryContext(ctx, blockedByQuery, args...)
if err != nil {
if optionalBlockedTable(depTable) && isTableNotExistError(err) {
continue
}
return fmt.Errorf("get blocked-by info from %s: %w", depTable, err)
}
var depRows []blockingInfoRow
var blockerIDs []string
for rows.Next() {
var row blockingInfoRow
if scanErr := rows.Scan(&row.issueID, &row.blockerID, &row.depType); scanErr != nil {
_ = rows.Close()
return fmt.Errorf("get blocking info: scan blocked-by: %w", scanErr)
}
depRows = append(depRows, row)
blockerIDs = append(blockerIDs, row.blockerID)
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return fmt.Errorf("get blocking info: blocked-by rows: %w", err)
}
statusByID, err := loadStatusByIDInTx(ctx, tx, blockerIDs)
if err != nil {
return fmt.Errorf("get blocking info: blocker status: %w", err)
}
for _, row := range depRows {
if statusByID[row.blockerID] == types.StatusClosed {
continue
}
if row.depType == "parent-child" {View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped scan error to identify the failing column and value.
- Find and repair rows with NULLs: SELECT * FROM <dep table> WHERE issue_id IS NULL OR type IS NULL OR depends_on_id IS NULL.
- Re-run schema migrations to restore expected column definitions.
- Restore the database from a known-good backup if rows are corrupted.
- Align driver/server versions to avoid conversion differences.
Example fix
// before: dependency row with NULL type fails Scan
INSERT INTO dependencies (issue_id, depends_on_id, type) VALUES ('bd-1', 'bd-2', NULL);
// after: always set the required columns
INSERT INTO dependencies (issue_id, depends_on_id, type) VALUES ('bd-1', 'bd-2', 'blocks'); Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-check for unscannable (NULL) columns in dependency rows
var n int
if err := tx.QueryRowContext(ctx,
"SELECT COUNT(*) FROM dependencies WHERE issue_id IS NULL OR depends_on_id IS NULL OR type IS NULL").Scan(&n); err != nil {
return err
}
if n > 0 {
return fmt.Errorf("%d dependency rows have NULL columns; repair first", n)
} Type guard
func isScanBlockedByError(err error) bool {
return err != nil && strings.Contains(err.Error(), "scan blocked-by")
} Try / catch
blockedBy, blocks, parents, err := GetBlockingInfoForIssuesInTx(ctx, tx, ids)
if err != nil && isScanBlockedByError(err) {
// locate and repair the offending row before retrying
return repairNullDependencyRows(ctx, tx)
} Prevention
- Declare issue_id, depends_on_id and type as NOT NULL.
- Sanitize any data imported from external sources before insert.
- Never leave type NULL — it must be 'blocks' or 'parent-child'.
- Run bd doctor after restores to detect NULL/type drift.
When it happens
Trigger: Calling GetBlockingInfoForIssuesInTx when a dependency row has NULL issue_id, depends_on_id (per depTargetExpr), or type; or columns were altered to incompatible types by migration/hand-editing.
Common situations: Hand-edited or imported data with NULLs; partial schema migrations; rows restored from a mismatched-version backup; driver type-mapping differences after an upgrade.
Related errors
- get dependency counts: scan dependent: %w
- get dependency counts: scan blocker: %w
- failed to scan peer for migration: %w
- db: GetAllConfig: scan: %w
- db: GetCustomTypes: scan custom_types: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/fb03334189767c8c.
Report an issue: GitHub.