gastownhall/beads · error

query cross-table duplicates: %w

Error message

query cross-table duplicates: %w

What it means

CountCrossTableDuplicates runs a read-only `SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)` used by the doctor's check phase. If the query/scan fails (as opposed to the DB being unreachable, which is reported earlier), it wraps the cause as "query cross-table duplicates: %w" and returns 0, forcing the caller to treat the count as unavailable.

Source

Thrown at cmd/bd/doctor/fix/validation.go:314

// CountCrossTableDuplicates returns the number of IDs present in both the
// issues and wisps tables. Returns 0 and an error if the database is
// unreachable. Used by CheckCrossTableDuplicates in the doctor package.
func CountCrossTableDuplicates(path string) (int, error) {
	beadsDir, err := resolvedWorkspaceBeadsDir(path)
	if err != nil {
		return 0, err
	}

	db, _, err := openDoltDB(beadsDir)
	if err != nil {
		return 0, err
	}
	defer db.Close()

	var count int
	if err := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count); err != nil {
		return 0, fmt.Errorf("query cross-table duplicates: %w", err)
	}
	return count, nil
}

// openDoltDB opens a Dolt database connection via MySQL protocol.
// Delegates to openFixDB for DSN construction (timeout + password support).
// Also returns the loaded config so callers that need it afterward (e.g. to
// verify the connection's target identity) don't have to load it a second
// time and risk it disagreeing with what was actually dialed.
func openDoltDB(beadsDir string) (*sql.DB, *configfile.Config, error) {
	cfg, err := configfile.Load(beadsDir)
	if err != nil || cfg == nil {
		return nil, nil, fmt.Errorf("no database configuration found")
	}

	db, err := openFixDB(beadsDir, cfg)
	if err != nil {
		return nil, nil, fmt.Errorf("dolt server connection failed: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Apply schema migrations so the wisps table exists (or skip the check on schemas without it)
  2. Verify the Dolt server stayed up during the doctor run; re-run the check
  3. Confirm SELECT privileges on both issues and wisps for the configured DB user
  4. Check .beads config points to the intended, current database

Example fix

// before: hard failure when wisps is missing
var count int
if err := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count); err != nil {
    return 0, fmt.Errorf("query cross-table duplicates: %w", err)
}
// after: tolerate missing wisps table as count 0
var count int
err := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count)
if err != nil && strings.Contains(err.Error(), "doesn't exist") {
    return 0, nil
} else if err != nil {
    return 0, fmt.Errorf("query cross-table duplicates: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that the wisps table exists so COUNT(*) won't fail
var n int
_ = db.QueryRow(`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'wisps'`).Scan(&n)
if n == 0 {
    return 0, nil // schema predates wisps: no duplicates possible
}

Try / catch

count, err := CountCrossTableDuplicates(path)
if err != nil {
    if strings.Contains(err.Error(), "doesn't exist") {
        count = 0 // old schema: treat as clean
    } else {
        log.Printf("duplicate check skipped: %v", err)
    }
}

Prevention

When it happens

Trigger: db.QueryRow(...).Scan(&count) fails — most commonly the wisps table doesn't exist in an unmigrated database, or the connection broke between openDoltDB's Ping and this query.

Common situations: Older repos lacking the wisps table (pre-migration schema); Dolt server restarted between connect and query; permission errors selecting from wisps; type-conversion issues scanning COUNT(*) (rare).

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/03a180fb4dbed298. Report an issue: GitHub.