gastownhall/beads · error

failed to query existing issues for prefix %q: %w

Error message

failed to query existing issues for prefix %q: %w

What it means

When no issue_counter row exists for a prefix, the seeder scans existing issues with a LIKE query to find the highest numeric suffix; failure of that scan query is wrapped with this message. The counter cannot be safely seeded without this scan, so the operation aborts.

Source

Thrown at internal/storage/dolt/issues.go:808

// It is idempotent: if a counter row already exists for this prefix, it does nothing.
func seedCounterFromExistingIssuesTx(ctx context.Context, tx *sql.Tx, prefix string) error {
	// Check whether a counter row already exists for this prefix.
	// If it does, we must not overwrite it (the counter may already be in use).
	var existing int
	err := tx.QueryRowContext(ctx, "SELECT last_id FROM issue_counter WHERE prefix = ?", prefix).Scan(&existing)
	if err == nil {
		// Row exists - counter is already initialized, nothing to do.
		return nil
	}
	if err != sql.ErrNoRows {
		return fmt.Errorf("failed to check issue_counter for prefix %q: %w", prefix, err)
	}

	// No counter row yet. Scan existing issues to find the highest numeric suffix.
	likePattern := prefix + "-%"
	rows, err := tx.QueryContext(ctx, "SELECT id FROM issues WHERE id LIKE ?", likePattern)
	if err != nil {
		return fmt.Errorf("failed to query existing issues for prefix %q: %w", prefix, err)
	}
	defer rows.Close()

	maxNum := 0
	prefixDash := prefix + "-"
	for rows.Next() {
		var id string
		if err := rows.Scan(&id); err != nil {
			return fmt.Errorf("failed to scan issue id: %w", err)
		}
		// Strip the prefix and attempt to parse the remainder as an integer.
		suffix := strings.TrimPrefix(id, prefixDash)
		if suffix == id {
			// id did not start with prefix- (should not happen given LIKE, but be safe)
			continue
		}
		var num int
		if _, parseErr := fmt.Sscanf(suffix, "%d", &num); parseErr == nil && fmt.Sprintf("%d", num) == suffix {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause and fix the underlying SQL/connection error
  2. Retry the operation; seeding is read-only up to the failure point
  3. Verify the issues table exists and is queryable (bd list)
  4. Ensure schema migrations ran so both issues and issue_counter are present
Defensive patterns

Strategy: retry

Validate before calling

// Ensure the issues table exists and is readable before creating issues
const count = await query("SELECT COUNT(*) FROM issues");

Try / catch

try {
  await bd.create(title);
} catch (e) {
  if (String(e.message).includes("failed to query existing issues")) {
    // check connectivity/migrations, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: First ID generation for a prefix with no counter row, where SELECT id FROM issues WHERE id LIKE 'prefix-%' fails — SQL error, transaction failure, or backend unavailable.

Common situations: Databases created before the counter table existed (legacy data being adopted); transient connection loss during first create after migration; very large issue tables timing out.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/b796f384db731e7f. Report an issue: GitHub.