gastownhall/beads · error

query issues: %w

Error message

query issues: %w

What it means

DeleteIssuesBySourceRepoInTx first SELECTs ids of all issues matching the given source_repo; any driver failure there is wrapped as "query issues: %w". This is the entry-point read for a bulk delete by source repository.

Source

Thrown at internal/storage/issueops/bulk_ops.go:178

			}
			result[c.IssueID] = append(result[c.IssueID], &c)
		}
		if err := rows.Err(); err != nil {
			_ = rows.Close()
			return err
		}
		_ = rows.Close()
	}
	return nil
}

// DeleteIssuesBySourceRepoInTx removes all issues from a source repo and their related data.
//
//nolint:gosec // G201: table is validated by hardcoded list
func DeleteIssuesBySourceRepoInTx(ctx context.Context, tx *sql.Tx, sourceRepo string) (int, error) {
	rows, err := tx.QueryContext(ctx, `SELECT id FROM issues WHERE source_repo = ?`, sourceRepo)
	if err != nil {
		return 0, fmt.Errorf("query issues: %w", err)
	}
	var issueIDs []string
	for rows.Next() {
		var id string
		if err := rows.Scan(&id); err != nil {
			_ = rows.Close()
			return 0, fmt.Errorf("scan issue ID: %w", err)
		}
		issueIDs = append(issueIDs, id)
	}
	_ = rows.Close()

	if len(issueIDs) == 0 {
		return 0, nil
	}

	affectedIssues, affectedWisps, aerr := AffectedByDeletionInTx(ctx, tx, issueIDs, nil)
	if aerr != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped driver error to identify the root cause (no such table, database is locked, context deadline)
  2. Ensure the schema is migrated to the current version
  3. Retry the whole transaction on transient busy/lock errors; the delete is transactional so partial state is rolled back
  4. Raise the context timeout for repos with very large issue counts

Example fix

// before: short context on a huge repo
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// after: generous timeout for bulk delete
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm connectivity and schema before the bulk op
if err := db.PingContext(ctx); err != nil { /* fail fast */ }

Type guard

if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { /* handle timeout */ }

Try / catch

n, err := DeleteIssuesBySourceRepoInTx(ctx, tx, repo)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        // retry the entire transaction with a longer timeout
    }
    return err
}

Prevention

When it happens

Trigger: tx.QueryContext on `SELECT id FROM issues WHERE source_repo = ?` fails: issues table missing, transaction already aborted, context canceled/deadline exceeded, or database locked/busy.

Common situations: Older database without the expected issues schema; long-running delete hitting context timeout; concurrent writer holding the SQLite lock; reusing a tx that a previous error already rolled back.

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


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