gastownhall/beads · error
failed to scan existing issues for prefix %q: %w
Error message
failed to scan existing issues for prefix %q: %w
What it means
The query 'SELECT id FROM issues WHERE id LIKE CONCAT(?, '-%')' used to discover the highest existing issue number for a prefix failed at execution time. The wrapper is purely contextual; the wrapped driver error carries the actual cause.
Source
Thrown at internal/storage/issueops/helpers.go:284
return fmt.Sprintf("%s-%d", prefix, nextID), nil
}
// SeedCounterFromExistingIssuesTx scans existing issues to find the highest numeric suffix
// for the given prefix, then seeds the issue_counter table if no row exists yet.
func SeedCounterFromExistingIssuesTx(ctx context.Context, tx DBTX, prefix string) error {
var existing int
err := tx.QueryRowContext(ctx, "SELECT last_id FROM issue_counter WHERE prefix = ?", prefix).Scan(&existing)
if err == nil {
return nil // already seeded
}
if err != sql.ErrNoRows {
return fmt.Errorf("failed to check existing counter for prefix %q: %w", prefix, err)
}
// Find max numeric suffix among existing issues
rows, err := tx.QueryContext(ctx, `SELECT id FROM issues WHERE id LIKE CONCAT(?, '-%')`, prefix)
if err != nil {
return fmt.Errorf("failed to scan existing issues for prefix %q: %w", prefix, err)
}
defer rows.Close()
maxNum := 0
pfxDash := prefix + "-"
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
continue
}
suffix := strings.TrimPrefix(id, pfxDash)
if strings.Contains(suffix, ".") {
continue // skip child IDs
}
if n, err := strconv.Atoi(suffix); err == nil && n > maxNum {
maxNum = n
}
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped error: if the tx was invalidated by an earlier failure, restart the whole operation in a new transaction.
- Run schema migrations to ensure the issues table exists with expected columns.
- If the driver lacks CONCAT support (non-Dolt SQLite backends), ensure you are using the correct storage driver for your database.
- Retry on transient connection errors; check DB connectivity logs.
Example fix
// before: reusing a failed tx
if err != nil { return err } // earlier failure left tx dead
rows, err := tx.QueryContext(...) // 'failed to scan existing issues'
// after: abort and retry the entire unit in a fresh transaction
if err != nil { return retryWithNewTx(op) } Defensive patterns
Strategy: retry
Validate before calling
if _, err := tx.QueryContext(ctx, "SELECT 1 FROM issues LIMIT 1"); err != nil {
return fmt.Errorf("issues table unavailable: %w", err)
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to scan existing issues") {
// abandon the poisoned tx and retry in a fresh one
tx.Rollback()
return retryWithFreshTx(ctx, op)
} Prevention
- Never continue using a transaction after an error; roll back and start fresh.
- Run migrations so the issues table and expected columns exist.
- Use the Dolt driver for Dolt databases so CONCAT-based LIKE patterns are supported.
When it happens
Trigger: SeedCounterFromExistingIssuesTx (via NextCounterIDTx) on an unseeded prefix: tx.QueryContext on the issues table fails — table missing, CONCAT/LIKE incompatibility with the driver, connection error, or transaction already aborted by a prior error.
Common situations: Schema drift (issues table renamed/absent); using a driver that doesn't support CONCAT in LIKE patterns; issuing the call on a transaction that earlier failed and was invalidated.
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
- ErrTransaction
- ErrQuery
- open unit of work: %w
- failed to begin transaction: %w
- failed to commit is_blocked repairs: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6cf5750410423b7c.
Report an issue: GitHub.