gastownhall/beads · error
failed to check existing counter for prefix %q: %w
Error message
failed to check existing counter for prefix %q: %w
What it means
SeedCounterFromExistingIssuesTx probes the issue_counter table to see if the prefix is already seeded; the probe failed with an error other than 'no rows'. This is a database-level failure (table missing, connection error, query error), not a 'not seeded yet' condition.
Source
Thrown at internal/storage/issueops/helpers.go:278
var nextID int
err = tx.QueryRowContext(ctx, "SELECT last_id FROM issue_counter WHERE prefix = ?", prefix).Scan(&nextID)
if err != nil {
return "", fmt.Errorf("failed to read issue counter after increment for prefix %q: %w", prefix, err)
}
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, ".") {View on GitHub (pinned to 71377f2769)
Solutions
- Apply schema migrations so issue_counter exists, then retry (the seeding will then succeed or find the row).
- Inspect the wrapped error: 'no such table' → migrate; permission denied → grant SELECT on issue_counter.
- Verify DB file integrity / re-clone via 'bd bootstrap' if the .beads database is corrupted.
- Check driver connection health before the operation if errors are transient.
Example fix
// before: old DB without issue_counter table
// after
if err := storage.Migrate(ctx, db); err != nil { return err }
id, err := storage.GenerateIssueIDInTable(ctx, tx, "issues", prefix, issue) Defensive patterns
Strategy: validation
Validate before calling
if _, err := tx.QueryContext(ctx, "SELECT 1 FROM issue_counter LIMIT 1"); err != nil {
return fmt.Errorf("run migrations: issue_counter table unavailable: %w", err)
} Try / catch
id, err := storage.GenerateIssueIDInTable(ctx, tx, "issues", prefix, issue)
if err != nil && strings.Contains(err.Error(), "failed to check existing counter") {
if mErr := storage.Migrate(ctx, db); mErr != nil { return mErr }
id, err = storage.GenerateIssueIDInTable(ctx, tx, "issues", prefix, issue)
} Prevention
- Gate counter mode on a migration check at startup.
- Treat any non-ErrNoRows error from the counter probe as a hard infra failure, not a seeding gap.
- Keep driver and schema versions in sync (bd upgrade + migrate together).
When it happens
Trigger: Called from NextCounterIDTx when an UPDATE on issue_counter matched 0 rows: the initial SELECT last_id ... Scan returns a non-ErrNoRows error — most commonly 'no such table: issue_counter' on an unmigrated Dolt database.
Common situations: Database created before counter-mode migration; corrupted or partially restored .beads Dolt database; connecting to a DB with insufficient privileges to read issue_counter.
Related errors
- failed to insert initial issue counter for prefix %q: %w
- schema: read database name: %w
- schema migration: %w
- failed to read issue counter after increment for prefix %q:
- failed to seed issue counter for prefix %q at %d: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/65fca9ab5dd8fd3d.
Report an issue: GitHub.