gastownhall/beads · error
stage repaired %s: %w
Error message
stage repaired %s: %w
What it means
After clearing constraint violations, the repaired table is staged with CALL DOLT_ADD('<t>') so the fix is part of the merge commit. Failure means the repaired rows are deleted but unstaged, so the merge will not capture the fix. Repair aborts with this wrapped error.
Source
Thrown at internal/storage/versioncontrolops/mergesettle.go:880
if !issueFKOnly {
return false, true, nil
}
}
for _, t := range tables {
res, err := db.ExecContext(ctx, fkCascadeRepairDeletes[t])
if err != nil {
return false, true, fmt.Errorf("cascade-repair %s: %w", t, err)
}
n, _ := res.RowsAffected()
// t is from the fixed fkCascadeRepairDeletes allowlist, never user input.
//nolint:gosec // G201/G202: hardcoded table name.
if _, err := db.ExecContext(ctx, "DELETE FROM dolt_constraint_violations_"+t); err != nil {
return false, true, fmt.Errorf("clear %s constraint violations: %w", t, err)
}
//nolint:gosec // G202: hardcoded table name.
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+t+"')"); err != nil {
return false, true, fmt.Errorf("stage repaired %s: %w", t, err)
}
fmt.Fprintf(os.Stderr,
"Notice: pull merged %s row(s) referencing issue(s) deleted on another clone; applied the foreign key's cascade delete (%d row(s) removed)\n",
t, n)
}
// The repair must leave nothing behind: a residual violation here means the
// deletes above did not cover the constraint that fired, and committing
// would persist a violated working set.
remaining, err := constraintViolationTables(ctx, db)
if err != nil {
return false, true, err
}
if len(remaining) > 0 {
return false, true, nil
}
return true, true, nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped %w error for the engine-side cause.
- Run CALL DOLT_ADD('<table>') manually inside the same session to see the raw error.
- If the merge is stuck, DOLT_MERGE_ABORT() and redo the pull/settle.
- Ensure only one bd/dolt process is operating on the database during settle.
Example fix
// before
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+t+"')"); err != nil {
return false, true, fmt.Errorf("stage repaired %s: %w", t, err)
}
// after: retry staging once before giving up
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+t+"')"); err != nil {
if _, rerr := db.ExecContext(ctx, "CALL DOLT_ADD('"+t+"')"); rerr != nil {
return false, true, fmt.Errorf("stage repaired %s: %w", t, rerr)
}
} Defensive patterns
Strategy: retry
Validate before calling
// confirm the table exists in the working set before staging
var one int
_ = db.QueryRow("SELECT 1 FROM issues LIMIT 1").Scan(&one) Try / catch
if _, _, err := TryRepairFKCascadeViolations(ctx, db); err != nil && strings.Contains(err.Error(), "stage repaired") {
// rows deleted but unstaged: abort merge and redo the pull
_, _ = db.ExecContext(ctx, "CALL DOLT_MERGE_ABORT()")
return retryPull(ctx)
} Prevention
- Single-writer discipline during merge settle
- Retry staging before aborting the merge
- Keep Dolt version consistent across clones
When it happens
Trigger: DOLT_ADD fails for table t — merge transaction in an inconsistent state, working-set/table not recognized by the engine, server refuses DOLT_ADD inside the current transaction, or table was dropped by the schema side of the merge.
Common situations: Engine/server version differences in DOLT_ADD behavior during a merge; interrupted settle leaving metadata inconsistent; permission or lock conflicts with another bd process.
Related errors
- dolt add %s after SQL mutation: %w: %w
- failed to stage is_blocked repairs: %w
- failed to stage %s before commit: %w
- check staged changes before commit: %w
- staging seeded dolt_ignore patterns: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5a36791ead22d661.
Report an issue: GitHub.