gastownhall/beads · error
failed to get stale issues: %w
Error message
failed to get stale issues: %w
What it means
GetStaleIssuesInTx builds and runs a SQL query selecting issue IDs not updated within the filter window (and without a live heartbeat), and wraps any QueryContext failure with this message. It indicates the database rejected or failed to execute the stale-issues SELECT, before any rows were read. The underlying driver error is preserved via %w.
Source
Thrown at internal/storage/issueops/stale.go:66
)%s
ORDER BY updated_at ASC
`, statusClause, labelClause)
args := []interface{}{cutoff}
if filter.Status != "" {
args = append(args, filter.Status)
}
args = append(args, cutoff) // NOT EXISTS heartbeat cutoff, after any status arg
// Label placeholders sit after the NOT EXISTS in the query text, so their
// args go last.
args = append(args, labelArgs...)
if filter.Limit > 0 {
query += fmt.Sprintf(" LIMIT %d", filter.Limit)
}
rows, err := tx.QueryContext(ctx, query, args...)
if err != nil {
return nil, fmt.Errorf("failed to get stale issues: %w", err)
}
// Collect IDs first, then batch-fetch full issues.
// Close rows explicitly before the nested fetch — MySQL/Dolt drivers
// can't handle multiple active result sets on one connection.
var ids []string
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
rows.Close()
return nil, fmt.Errorf("failed to scan stale issue id: %w", err)
}
ids = append(ids, id)
}
if err := rows.Err(); err != nil {
rows.Close()
return nil, fmt.Errorf("stale issues rows: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error to identify the root cause (missing table, connection lost, cancelled context).
- Verify the database schema is current (issues and leases tables exist with expected columns); run the app's migration/doctor command.
- Check that the *sql.Tx passed in is still open and its connection is alive; retry the whole operation with a fresh transaction if the connection dropped.
- If it's a context deadline, raise the timeout or narrow the filter (smaller Days window or a Limit) so the scan is cheaper.
Example fix
// before
issues, err := GetStaleIssuesInTx(ctx, brokenTx, filter)
// after
tx, err := store.BeginTx(ctx)
if err != nil { return err }
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
issues, err := GetStaleIssuesInTx(ctx, tx, filter) Defensive patterns
Strategy: retry
Validate before calling
// caller-side pre-check
if tx == nil { return fmt.Errorf("no active transaction") }
if err := ctx.Err(); err != nil { return fmt.Errorf("context already done: %w", err) } Try / catch
issues, err := issueops.GetStaleIssuesInTx(ctx, tx, filter)
if err != nil {
var retryable = errors.Is(err, sql.ErrConnDone) || ctx.Err() == nil
if retryable { /* retry with fresh tx */ }
return fmt.Errorf("stale scan failed: %w", err)
} Prevention
- Always pass a live tx and a context with a sane timeout
- Run schema migrations before issuing stale queries
- Wrap long scans in retry-with-backoff on transient driver errors
- Keep the StaleFilter narrow (Limit/Days) on large databases
When it happens
Trigger: Calling GetStaleIssuesInTx when the transaction/connection is broken or closed, the issues or leases table is missing or corrupted, the SQL text plus interpolated LIMIT and label clauses is malformed, or the context is cancelled/times out mid-query.
Common situations: Running against a database where a migration didn't create the leases table; a context deadline exceeded during a large stale scan; Dolt server restarts mid-transaction; passing a StaleFilter with unusual label sets that produce a bad clause.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- failed to get federation peer: %w
- db: CommentSQLRepository.CountsByIssueIDs: %w
- db: CommentSQLRepository.ListByIssueIDs: %w
- db: LabelSQLRepository.ListByIssueIDs: %w
- ErrQuery
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ed432e7b4ec2c42b.
Report an issue: GitHub.