gastownhall/beads · error
scan wisp dependent: %w
Error message
scan wisp dependent: %w
What it means
During the recursive wisp-dependents traversal, scanning a row's issue_id into a string failed. This wraps rows.Scan errors — the row shape didn't match the expected single string column. The row set is closed and traversal aborts, returning the partial discovered set.
Source
Thrown at internal/storage/issueops/bulk_ops.go:396
if end > len(toProcess) {
end = len(toProcess)
}
batch := toProcess[:end]
toProcess = toProcess[end:]
placeholders, args := buildSQLInClause(batch)
rows, err := tx.QueryContext(ctx,
fmt.Sprintf(`SELECT issue_id FROM wisp_dependencies WHERE %s IN (%s)`, DepTargetExpr, placeholders),
args...)
if err != nil {
return discovered, fmt.Errorf("query wisp dependents: %w", err)
}
for rows.Next() {
var depID string
if err := rows.Scan(&depID); err != nil {
_ = rows.Close()
return discovered, fmt.Errorf("scan wisp dependent: %w", err)
}
if !seen[depID] {
seen[depID] = true
discovered[depID] = true
toProcess = append(toProcess, depID)
}
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return discovered, fmt.Errorf("iterate wisp dependents: %w", err)
}
}
return discovered, nil
}
// GetRepoMtimeInTx returns the cached mtime (nanoseconds) for a repo path.
// Returns 0 if no cache entry exists.View on GitHub (pinned to 71377f2769)
Solutions
- Run pending schema migrations so wisp_dependencies matches the expected shape.
- Check the wrapped error for NULL-vs-non-string mismatches and clean bad rows.
- Verify all replicas/nodes run the same beads version during upgrades.
- Retry after fixing the schema; the traversal is read-only so it is safe to re-run.
Example fix
// before // schema drift: issue_id column is NULLable and contains NULLs -> scan fails // after // migrate: UPDATE wisp_dependencies SET issue_id='' WHERE issue_id IS NULL; ALTER TABLE wisp_dependencies MODIFY issue_id TEXT NOT NULL;
Defensive patterns
Strategy: validation
Validate before calling
// preflight: ensure the column is present and non-NULL
row := db.QueryRow("SELECT COUNT(*) FROM wisp_dependencies WHERE issue_id IS NULL")
var n int; _ = row.Scan(&n)
if n > 0 { return fmt.Errorf("%d rows with NULL issue_id; run migration first", n) } Try / catch
_, err := store.FindWispDependentsRecursive(ctx, tx, rootID, max)
if err != nil && strings.Contains(err.Error(), "scan wisp dependent:") {
return fmt.Errorf("wisp_dependencies schema mismatch; run migrations: %w", err)
} Prevention
- Run migrations before deploying new beads versions.
- Add a NULL/shape preflight check on wisp_dependencies in CI.
- Keep all replicas on the same schema version.
When it happens
Trigger: Calling FindWispDependentsRecursiveInTx when the wisp_dependencies row returned has a different column type/shape than expected — e.g. schema drift after an upgrade, or DepTargetExpr resolving to a non-string column.
Common situations: Running new code against an old (unmigrated) wisp_dependencies table; a driver returning NULL for issue_id into a non-nullable string scan; mixed-version replicas during a rolling upgrade.
Related errors
- failed to scan federation peer: %w
- failed to scan comment: %w
- failed to get issue from %s: %w
- descendants: wisp_dependencies probe: %w
- db: ListRemotes: scan: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ec228accc63392e9.
Report an issue: GitHub.