{"record":{"id":"03a180fb4dbed298","repo":"gastownhall/beads","slug":"query-cross-table-duplicates-w","errorCode":null,"errorMessage":"query cross-table duplicates: %w","messagePattern":"query cross-table duplicates: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/fix/validation.go","lineNumber":314,"sourceCode":"\n// CountCrossTableDuplicates returns the number of IDs present in both the\n// issues and wisps tables. Returns 0 and an error if the database is\n// unreachable. Used by CheckCrossTableDuplicates in the doctor package.\nfunc CountCrossTableDuplicates(path string) (int, error) {\n\tbeadsDir, err := resolvedWorkspaceBeadsDir(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tdb, _, err := openDoltDB(beadsDir)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer db.Close()\n\n\tvar count int\n\tif err := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count); err != nil {\n\t\treturn 0, fmt.Errorf(\"query cross-table duplicates: %w\", err)\n\t}\n\treturn count, nil\n}\n\n// openDoltDB opens a Dolt database connection via MySQL protocol.\n// Delegates to openFixDB for DSN construction (timeout + password support).\n// Also returns the loaded config so callers that need it afterward (e.g. to\n// verify the connection's target identity) don't have to load it a second\n// time and risk it disagreeing with what was actually dialed.\nfunc openDoltDB(beadsDir string) (*sql.DB, *configfile.Config, error) {\n\tcfg, err := configfile.Load(beadsDir)\n\tif err != nil || cfg == nil {\n\t\treturn nil, nil, fmt.Errorf(\"no database configuration found\")\n\t}\n\n\tdb, err := openFixDB(beadsDir, cfg)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"dolt server connection failed: %w\", err)","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/fix/validation.go#L296-L332","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Apply schema migrations so the wisps table exists (or skip the check on schemas without it)","Verify the Dolt server stayed up during the doctor run; re-run the check","Confirm SELECT privileges on both issues and wisps for the configured DB user","Check .beads config points to the intended, current database"],"exampleFix":"// before: hard failure when wisps is missing\nvar count int\nif err := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count); err != nil {\n    return 0, fmt.Errorf(\"query cross-table duplicates: %w\", err)\n}\n// after: tolerate missing wisps table as count 0\nvar count int\nerr := db.QueryRow(`SELECT COUNT(*) FROM issues WHERE id IN (SELECT id FROM wisps)`).Scan(&count)\nif err != nil && strings.Contains(err.Error(), \"doesn't exist\") {\n    return 0, nil\n} else if err != nil {\n    return 0, fmt.Errorf(\"query cross-table duplicates: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// Pre-check that the wisps table exists so COUNT(*) won't fail\nvar n int\n_ = db.QueryRow(`SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'wisps'`).Scan(&n)\nif n == 0 {\n    return 0, nil // schema predates wisps: no duplicates possible\n}","typeGuard":null,"tryCatchPattern":"count, err := CountCrossTableDuplicates(path)\nif err != nil {\n    if strings.Contains(err.Error(), \"doesn't exist\") {\n        count = 0 // old schema: treat as clean\n    } else {\n        log.Printf(\"duplicate check skipped: %v\", err)\n    }\n}","preventionTips":["Apply migrations before running doctor checks that reference wisps","Treat a failed count as 'unknown', not 'zero duplicates'","Verify server uptime and privileges on both tables before checks","Keep the connection alive between openDoltDB and the count query (short sessions)"],"tags":["database","sql-query","mysql","dolt"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}