{"record":{"id":"4384ba1b4a7c163c","repo":"gastownhall/beads","slug":"count-s-orphans-w","errorCode":null,"errorMessage":"count %s orphans: %w","messagePattern":"count (.+?) orphans: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/fix/clone_local_fks.go","lineNumber":102,"sourceCode":"\t\tif err := db.QueryRow(\n\t\t\t`SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS\n\t\t\t WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND CONSTRAINT_NAME = ? AND CONSTRAINT_TYPE = 'FOREIGN KEY'`,\n\t\t\tfk.Table, fk.Constraint,\n\t\t).Scan(&constraints); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"check %s.%s: %w\", fk.Table, fk.Constraint, err)\n\t\t}\n\t\tif constraints > 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tvar orphans int\n\t\t//nolint:gosec // G201: identifiers come from the fixed CloneLocalFKs spec above, not user input.\n\t\torphanCount := fmt.Sprintf(\n\t\t\t`SELECT COUNT(*) FROM %s t WHERE t.%s IS NOT NULL AND NOT EXISTS (SELECT 1 FROM %s r WHERE r.%s = t.%s)`,\n\t\t\tfk.Table, fk.Column, fk.RefTable, fk.RefColumn, fk.Column,\n\t\t)\n\t\tif err := db.QueryRow(orphanCount).Scan(&orphans); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"count %s orphans: %w\", fk.Table, err)\n\t\t}\n\n\t\tsevered = append(severed, SeveredCloneLocalFK{CloneLocalFK: fk, Orphans: orphans})\n\t}\n\treturn severed, nil\n}\n\n// CloneLocalFKEnforcement re-links severed clone-local FKs: for each missing\n// constraint it deletes the orphaned rows that accumulated while enforcement\n// was off (ADD CONSTRAINT validates existing rows, so they must go first),\n// then re-adds the constraint in place. Verified on dolt 2.2.2: the re-added\n// FK resolves against the current tracked root and enforces again.\nfunc CloneLocalFKEnforcement(path string, verbose bool) error {\n\tbeadsDir, err := resolvedWorkspaceBeadsDir(path)\n\tif err != nil {\n\t\treturn err\n\t}\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/fix/clone_local_fks.go#L84-L120","documentation":"For each spec'd FK whose constraint is missing, scanSeveredCloneLocalFKs counts orphaned rows via a generated NOT EXISTS query (identifiers come from the fixed CloneLocalFKs spec, not user input). If that count query fails, the scan returns this wrapped error instead of a SeveredCloneLocalFK entry.","triggerScenarios":"The dynamically built orphan-count SELECT fails in scanSeveredCloneLocalFKs (cmd/bd/doctor/fix/clone_local_fks.go:102) — typically a storage/driver failure mid-scan or a table that exists but cannot be read.","commonSituations":"Large orphan scans hitting storage timeouts, a partially migrated schema where fk.Column/fk.RefTable no longer match the actual tables, or Dolt read errors on a cloned repo.","solutions":["Inspect the wrapped driver error and re-run `bd doctor` after the storage issue is resolved.","Verify the actual schema matches the CloneLocalFKs spec (table/column names) after any manual migration.","Check for disk/lock issues in the .beads Dolt store and free space or clear locks.","Reduce scan size by repairing one workspace at a time if timeouts are the cause."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm spec'd tables/columns still exist before the orphan count runs:\nrows, _ := db.Query(`SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS`)\n// compare against CloneLocalFKs entries; mismatch = schema drift to fix first","typeGuard":null,"tryCatchPattern":"severed, err := ScanSeveredCloneLocalFKs(ctx, db)\nif err != nil && strings.Contains(err.Error(), \"count\") {\n\t// orphan-count failure: fix schema drift or storage, then rescan\n\treturn err\n}","preventionTips":["Don't manually rename FK tables/columns that the CloneLocalFKs spec expects","Check disk space before large orphan scans","Run scans on a quiescent database (no concurrent writes)","Re-run doctor after failures; the scan is read-only and safe to repeat"],"tags":["dolt","doctor","foreign-keys","orphan-rows"],"backgroundTag":"database-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}