gastownhall/beads · error
schema: fresh-bootstrap reset: %w
Error message
schema: fresh-bootstrap reset: %w
What it means
During the fresh-bootstrap self-heal, after the dirty-tables guard fired, the library runs `CALL DOLT_RESET('--hard')` (drained on the pinned session). If that reset fails, the original DirtyTablesError is joined with this reset error and returned. This is a destructive recovery step failing, so migrations could not be re-run from a clean slate.
Source
Thrown at internal/storage/schema/lock.go:301
// database-scoped migration lock is still held. A mismatch, missing
// ancestor, probe error, or previously consumed capability returns the
// original DirtyTablesError without attempting a destructive reset.
if !o.freshBootstrapHeal.capability.consumeIfCurrentIncarnation(
ctx, conn, databaseName, o.freshBootstrapHeal.endpoint,
) {
return applied, err
}
// Consume occurs before the reset call. Thus a reset error or a
// transient failure in the following migration pass cannot re-arm a
// second reset in the caller's outer retry loop.
fmt.Fprintf(stderr, "Discarding interrupted-bootstrap working set (%s) and re-running migrations…\n",
strings.Join(dirtyErr.Tables, ", "))
// Drained, not Exec'd: the very next thing this path does is re-run the
// whole MigrateUp pass on this same pinned connection, so an
// undrained proc result set here would poison every statement of it.
if resetErr := DrainCall(ctx, conn, "CALL DOLT_RESET('--hard')"); resetErr != nil {
return applied, errors.Join(err, fmt.Errorf("schema: fresh-bootstrap reset: %w", resetErr))
}
applied, err = MigrateUp(ctx, conn)
}
return applied, err
}
// consumeIfCurrentIncarnation validates and atomically consumes c. All probes
// run on the same pinned session while MigrateUpWithLock holds the migration
// lock. Query errors deliberately collapse to false so callers preserve and
// return the original DirtyTablesError.
func (c *FreshBootstrapHealCapability) consumeIfCurrentIncarnation(
ctx context.Context,
conn *sql.Conn,
databaseName string,
endpoint string,
) bool {
if c == nil || c.consumed.Load() {
return falseView on GitHub (pinned to 71377f2769)
Solutions
- Inspect both joined errors; fix the reset cause (connectivity, server health) before retrying.
- Retry the open: the capability is consumed, so a retry takes the normal path; manually run DOLT_RESET('--hard') if you've confirmed the working set is disposable.
- Check server logs for why DOLT_RESET failed (read-only filesystem, lock conflicts).
- As a last resort drop and recreate the database if it's genuinely fresh/disposable.
Example fix
// before
// capability consumed, reset failed; blind outer retry does nothing
// after
// verify and reset manually once server is healthy:
// CALL DOLT_RESET('--hard');
applied, err := schema.MigrateUpWithLock(ctx, conn, dbName) Defensive patterns
Strategy: try-catch
Validate before calling
// before opting into heal, confirm reset is acceptable:
// the database must be freshly created this logical open (hold the capability)
if cap == nil { /* heal disabled; dirty tables are fatal */ } Type guard
var dirtyErr *schema.DirtyTablesError
if errors.As(err, &dirtyErr) && strings.Contains(err.Error(), "fresh-bootstrap reset") {
// heal reset itself failed
} Try / catch
applied, err := schema.MigrateUpWithLock(ctx, conn, db, schema.WithFreshBootstrapHeal(cap, endpoint))
if err != nil && strings.Contains(err.Error(), "fresh-bootstrap reset") {
// capability already consumed; fix server health, then either
// run CALL DOLT_RESET('--hard') manually or drop/recreate the db
} Prevention
- Verify server health (disk, restarts) before enabling the heal path.
- Remember the capability is one-shot: a failed reset requires manual intervention on retry.
- Check pinned-session hygiene (no undrained result sets) before the reset call.
- Keep an operator runbook for manually disposing interrupted-bootstrap working sets.
When it happens
Trigger: MigrateUpWithLock with WithFreshBootstrapHeal where MigrateUp returns DirtyTablesError, the capability validates and is consumed, but DOLT_RESET errors — server error, connection drop, or the proc result cannot be drained.
Common situations: Interrupted bootstrap left dirty tables AND the server is unhealthy (restart, disk full, permissions); a pinned session corrupted by earlier undrained result sets.
Related errors
- schema: capture fresh-bootstrap identity: %w
- schema: verify fresh-bootstrap history: %w
- schema: verify fresh-bootstrap history: got %d commits, want
- schema: verify fresh-bootstrap working set: %w
- schema: verify fresh-bootstrap working set: got %d dirty ent
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f1d86f4dd2a3796f.
Report an issue: GitHub.