gastownhall/beads · error

re-add %s.%s: %w

Error message

re-add %s.%s: %w

What it means

After removing orphaned rows, relinkSeveredCloneLocalFKs re-adds each missing foreign key with ALTER TABLE ... ADD CONSTRAINT. If the ALTER fails, this error wraps it, meaning the FK remains severed and future writes may not enforce referential integrity for clone-local references.

Source

Thrown at cmd/bd/doctor/fix/clone_local_fks.go:170

				fk.Table, fk.Column, fk.RefTable, fk.RefColumn, fk.Table, fk.Column,
			)
			result, err := db.Exec(deleteOrphans)
			if err != nil {
				return fmt.Errorf("delete %s orphans: %w", fk.Table, err)
			}
			if verbose {
				removed, _ := result.RowsAffected()
				fmt.Printf("  Removed %d orphaned row(s) from %s\n", removed, fk.Table)
			}
		}

		//nolint:gosec // G201: identifiers come from the fixed CloneLocalFKs spec, not user input.
		addConstraint := fmt.Sprintf(
			`ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) ON DELETE CASCADE ON UPDATE CASCADE`,
			fk.Table, fk.Constraint, fk.Column, fk.RefTable, fk.RefColumn,
		)
		if _, err := db.Exec(addConstraint); err != nil {
			return fmt.Errorf("re-add %s.%s: %w", fk.Table, fk.Constraint, err)
		}
		fmt.Printf("  ✓ Re-linked %s.%s (%d orphaned row(s) removed)\n", fk.Table, fk.Constraint, fk.Orphans)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the scan + fix (`bd doctor`) so orphans created in between are deleted before the constraint is re-added.
  2. Check the wrapped error for 'duplicate constraint' — if so, the constraint already exists and the scan is stale; rescan.
  3. Ensure the database user has ALTER privileges on the issues tables.
  4. Verify the actual schema matches the CloneLocalFKs spec (table/column names) after any migration.
Defensive patterns

Strategy: retry

Validate before calling

// Confirm no orphans remain and the constraint name is free:
var orphans int
db.QueryRow(`SELECT COUNT(*) FROM issues t WHERE t.<fk> IS NOT NULL AND NOT EXISTS (...)`).Scan(&orphans)
var cons int
db.QueryRow(`SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_NAME = ?`, fk.Constraint).Scan(&cons)
// orphans == 0 && cons == 0 means ALTER should succeed

Try / catch

if err := CloneLocalFKEnforcement(ctx, db, verbose); err != nil && strings.Contains(err.Error(), "re-add") {
	// ALTER failed: rescan (frees races/stale state), then retry once
	return err
}

Prevention

When it happens

Trigger: ALTER TABLE ADD CONSTRAINT fails in relinkSeveredCloneLocalFKs (cmd/bd/doctor/fix/clone_local_fks.go:170) — remaining orphan rows the delete step missed, duplicate constraint name, ALTER privileges denied, or Dolt engine rejecting the FK definition.

Common situations: Races where new orphans were inserted between delete and re-add, running with a DB user lacking ALTER privileges, schema drift after manual migrations renaming tables/columns away from the CloneLocalFKs spec.

Related errors


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