gastownhall/beads · error
scan blocker edge: %w
Error message
scan blocker edge: %w
What it means
Wraps a rows.Scan failure while reading (dependsOnID, depType) edge rows in IsBlockedInTx. The edge query succeeded but a returned row could not be scanned into two strings, indicating column type/shape mismatch or NULLs in the dep table.
Source
Thrown at internal/storage/issueops/dependency_queries.go:948
dependsOnID, depType string
}
var edges []depEdge
for _, depTable := range []string{"dependencies", "wisp_dependencies"} {
rows, err := tx.QueryContext(ctx, fmt.Sprintf(`
SELECT %s AS depends_on_id, type FROM %s
WHERE issue_id = ? AND type IN ('blocks', 'waits-for', 'conditional-blocks')
`, DepTargetExpr, depTable), issueID)
if err != nil {
if optionalBlockedTable(depTable) && isTableNotExistError(err) {
continue
}
return false, nil, fmt.Errorf("check blockers from %s: %w", depTable, err)
}
for rows.Next() {
var e depEdge
if err := rows.Scan(&e.dependsOnID, &e.depType); err != nil {
_ = rows.Close()
return false, nil, fmt.Errorf("scan blocker edge: %w", err)
}
edges = append(edges, e)
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return false, nil, fmt.Errorf("blocker edge rows from %s: %w", depTable, err)
}
}
if len(edges) == 0 {
return true, nil, nil
}
blockerIDs := make([]string, 0, len(edges))
for _, e := range edges {
blockerIDs = append(blockerIDs, e.dependsOnID)
}
statusByID, err := loadStatusByIDInTx(ctx, tx, blockerIDs)View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped scan error to find the offending column
- Ensure depends_on/id and type columns are TEXT NOT NULL per schema
- Recreate or migrate the dependency table to canonical schema
- Re-run the blocked check after repair
Example fix
// before SELECT depends_on_id, type FROM deps WHERE ... // after (defensive) SELECT COALESCE(depends_on_id,''), COALESCE(type,'') FROM deps WHERE ...
Defensive patterns
Strategy: try-catch
Validate before calling
// check column types
rows, _ := db.Query("SELECT typeof(depends_on_id), typeof(type) FROM deps LIMIT 1") Try / catch
if err := issueops.IsBlocked(ctx, id); err != nil {
if strings.Contains(err.Error(), "scan blocker edge") {
// schema drift: fix column types to TEXT, then retry
}
return err
} Prevention
- Only write dependency edges through bd commands
- Validate table schema after external restores/syncs
- Keep column types TEXT NOT NULL as defined by migrations
When it happens
Trigger: Iterating blocker edges when a dependency table row has unexpected column types (non-TEXT id/type columns, NULL values) or the table schema differs from what the query expects.
Common situations: Hand-edited or externally written dep tables with wrong column types; upgrade-related schema drift; corrupted rows.
Related errors
- scan remaining blocker: %w
- failed to scan dolt_status: %w
- scan dirty config key: %w
- db: ChildCounterSQLRepository.NextChildID: scan: %w
- db: CommentSQLRepository.CountsByIssueIDs: scan: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/adfc92a97f8a5846.
Report an issue: GitHub.