gastownhall/beads · error
iter issues: query
Error message
iter issues: query: %w
What it means
IterIssues failed when executing the constructed SELECT via tx.QueryContext inside a read transaction. The SQL was built but the database refused or could not run it. IterIssues materializes results eagerly, so this error aborts before any iterator is returned.
Solutions
- Read the wrapped driver error for the concrete SQL failure (unknown column, no such table, connection refused)
- Ensure the Dolt database/server is running and the .beads directory is intact
- Run schema migrations / bd doctor to align the DB schema with the binary
- Verify the custom query string is valid for the issues table
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check backend availability before iterating
if err := requireDoltBackend(fileCfg); err != nil { return err } Try / catch
iter, err := store.IterIssues(ctx, query, filter)
if err != nil && strings.Contains(err.Error(), "query:") {
// transient DB issue: retry with backoff
return retryWithBackoff(func() error { _, err = store.IterIssues(ctx, query, filter); return err })
} Prevention
- Ensure the Dolt server is running before batch operations
- Run bd doctor / migrations after upgrading beads
- Set adequate context timeouts for large queries
When it happens
Trigger: Calling IterIssues when the issues table or lease-joined columns are missing/renamed, the database is unavailable or locked, or the SQL text produced from the query+filter is invalid.
Common situations: Opening a .beads directory with a mismatched/empty Dolt database; Dolt server not running or crashed; schema migration not applied; column mismatch after upgrade.
Related errors
- counting nonlocal frozen rows
- failed to resolve conflicts
- failed to stage
- resolve existing wisps for batch delete
- add backup
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/35521e16f46a1cc8.
Report an issue: GitHub.
Appendix: source
Thrown at internal/storage/dolt/iter_issues.go:64
}
whereSQL := ""
if len(whereClauses) > 0 {
whereSQL = "WHERE " + strings.Join(whereClauses, " AND ")
}
limitSQL := ""
if filter.Limit > 0 {
limitSQL = fmt.Sprintf(" LIMIT %d", filter.Limit)
}
//nolint:gosec // G201: whereSQL contains column comparisons with ?, limitSQL is a safe integer
q := fmt.Sprintf(`SELECT %s FROM issues %s %s ORDER BY priority ASC, created_at DESC, id ASC%s`,
issueops.IssueSelectColumns, sqlbuild.LeaseJoin("issues"), whereSQL, limitSQL)
var issues []*types.Issue
txErr := s.withReadTx(ctx, func(tx *sql.Tx) error {
rows, err := tx.QueryContext(ctx, q, args...)
if err != nil {
return fmt.Errorf("iter issues: query: %w", err)
}
defer func() { _ = rows.Close() }()
ids := make([]string, 0)
for rows.Next() {
iss, scanErr := issueops.ScanIssueFrom(rows)
if scanErr != nil {
return fmt.Errorf("iter issues: scan: %w", scanErr)
}
issues = append(issues, iss)
ids = append(ids, iss.ID)
}
if err := rows.Err(); err != nil {
return fmt.Errorf("iter issues: rows: %w", err)
}
// A *sql.Tx is bound to one connection, so the cursor must be closed
// before the label query can run on it (idempotent with the defer).
_ = rows.Close()
labelMap, err := issueops.GetLabelsForIssuesFromTableInTx(ctx, tx, "labels", ids)View on GitHub (pinned to 71377f2769)