gastownhall/beads · error
failed to stage %s: %w
Error message
failed to stage %s: %w
What it means
This error wraps a failure from CALL DOLT_ADD(table) in TryAutoResolveMergeConflicts, which stages a table after its conflicts were resolved via '--theirs'. Dolt refuses to stage in some states — no such table, no merge in progress, or a storage engine error — and the wrapper adds the table name for diagnosis.
Source
Thrown at internal/storage/versioncontrolops/mergesettle.go:565
// Field-level three-way merge, not a table-level --ours/--theirs:
// a cell only one side changed keeps that side's value and only a
// genuinely contested cell falls to LWW (automerge.go).
if err := resolveIssuesFieldMerge(ctx, db, issuesPlan); err != nil {
return false, err
}
case "labels", "comments", "events":
if err := resolveUnionConflicts(ctx, db, table, unionPlans[table]); err != nil {
return false, err
}
default:
//nolint:gosec // G201: table is one of the hardcoded constants above.
if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--theirs', '"+table+"')"); err != nil {
return false, fmt.Errorf("failed to resolve %s conflicts: %w", table, err)
}
}
//nolint:gosec // G201: table is one of the hardcoded constants above.
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+table+"')"); err != nil {
return false, fmt.Errorf("failed to stage %s: %w", table, err)
}
}
return true, nil
}
// CommitResolvedConflicts creates the dolt commit that concludes a merge whose
// conflicts TryAutoResolveMergeConflicts settled. Callers that saw
// resolved=true MUST call this, and only AFTER TryRepairFKCascadeViolations
// has run: DOLT_COMMIT refuses a working set with outstanding constraint
// violations, so a merge carrying both an auto-resolvable conflict and an FK
// cascade violation could never settle while the resolver committed first
// (bd-578h9.14).
func CommitResolvedConflicts(ctx context.Context, db DBConn) error {
if _, err := db.ExecContext(ctx, "CALL DOLT_COMMIT('-m', 'auto-resolve merge conflicts: metadata, dependencies, schema_migrations, config, issues (field-level three-way merge), labels/comments/events (union)')"); err != nil {
return fmt.Errorf("failed to commit resolved conflicts: %w", err)
}
return nilView on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped inner error for the concrete Dolt message (unknown table, not in merge, lock timeout).
- Confirm the table still exists (SHOW TABLES / dolt_status) and the merge is still active before retrying SettleMerge.
- Serialize merge settlement — prevent concurrent bd processes from touching the same working set while conflicts resolve.
- Retry once after a transient lock error; if persistent, abort the merge (CALL DOLT_MERGE('--abort')) and re-merge cleanly.
Example fix
// before
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+table+"')"); err != nil {
return false, fmt.Errorf("failed to stage %s: %w", table, err)
}
// after
if _, err := db.ExecContext(ctx, "CALL DOLT_ADD('"+table+"')"); err != nil {
// transient lock/engine errors: abort merge so caller can retry from clean state
_, _ = db.ExecContext(ctx, "CALL DOLT_MERGE('--abort')")
return false, fmt.Errorf("failed to stage %s (merge aborted, safe to retry): %w", table, err)
} Defensive patterns
Strategy: retry
Validate before calling
var exists int err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = ?", table).Scan(&exists) // also confirm merge still active: SELECT COUNT(*) FROM dolt_conflicts > 0
Type guard
func tableExistsAndConflicted(ctx context.Context, db DBConn, table string) bool {
var n int
if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts WHERE `table` = ?", table).Scan(&n); err != nil || n == 0 {
return false
}
return true
} Try / catch
ok, err := TryAutoResolveMergeConflicts(ctx, db)
if err != nil && strings.Contains(err.Error(), "failed to stage") {
// transient staging failure: abort and retry the whole settle once
_, _ = db.ExecContext(ctx, "CALL DOLT_MERGE('--abort')")
// re-run merge + settle here
} Prevention
- Do not run concurrent writers on the same working set during merge settlement.
- Retry SettleMerge once from a clean state after any staging failure; staging errors are often transient state races.
- Verify the table still exists before settling if other code can drop/rename tables.
- Keep Dolt and the driver versions aligned with what mergesettle.go expects.
When it happens
Trigger: Immediately after successful conflict resolution, CALL DOLT_ADD('<table>') fails: the table was dropped mid-merge, the merge state was cleared by another connection, or the Dolt engine rejects the add (e.g. lock contention or an internal storage error).
Common situations: Concurrent writers staging/committing the same working set; a table renamed or dropped between conflict detection and staging; Dolt working-set metadata inconsistency after a crashed process; running against a Dolt version with different DOLT_ADD semantics.
Related errors
- iter issues: query: %w
- resolve existing wisps for batch delete: %w
- counting nonlocal frozen rows: %w
- failed to resolve %s conflicts: %w
- ErrExec
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2ecae5498966370e.
Report an issue: GitHub.