gastownhall/beads · warning

uow: bootstrap preparation: %w

Error message

uow: bootstrap preparation: %w

What it means

classifyInitSchemaError wraps an error from schema migration as 'uow: bootstrap preparation' when the error is a bootstrapPreparationError flagged retryable. It marks a database bootstrap/prepare step (CREATE DATABASE, USE, pre-migration prep under the migration lock) that failed transiently and will be retried by the backoff loop. The wrapping keeps the preparation context on the error while letting backoff.Retry continue.

Source

Thrown at internal/storage/uow/dolt_sql_provider.go:82

type bootstrapPreparationError struct {
	err       error
	retryable bool
}

func (e *bootstrapPreparationError) Error() string {
	return e.err.Error()
}

func (e *bootstrapPreparationError) Unwrap() error {
	return e.err
}

func classifyInitSchemaError(err error) error {
	var preparationErr *bootstrapPreparationError
	if errors.As(err, &preparationErr) {
		if preparationErr.retryable {
			return fmt.Errorf("uow: bootstrap preparation: %w", err)
		}
		return backoff.Permanent(err)
	}
	if isSerializationError(err) || schema.IsMigrationLockError(err) {
		return fmt.Errorf("uow: migrate: %w", err)
	}
	return backoff.Permanent(fmt.Errorf("uow: migrate: %w", err))
}

// ProviderOption tunes how a SQL-server unit-of-work provider opens. Options
// are variadic so the existing constructor call sites — every one of which
// wants the ordinary mutating open — stay unchanged.
type ProviderOption func(*providerOptions)

type providerOptions struct {
	// preview opens for a command that promised not to mutate anything
	// (--dry-run, --inspect). Such a command must reach its own RunE before
	// anything writes, so the open may neither CREATE DATABASE nor run

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry is automatic: the initSchema backoff loop (60s budget) will re-attempt; simply re-run the command if the process exited.
  2. Check that no other bd process is stuck holding the migration lock on the shared Dolt server.
  3. Verify Dolt server connectivity and load; transient failures under load are the usual cause.
  4. If it repeatedly fails, inspect the bootstrapPreparationError's wrapped cause for the underlying SQL error.
Defensive patterns

Strategy: retry

Validate before calling

// ensure server reachable before opening the provider
if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("dolt server unreachable, bootstrap will retry: %w", err)
}

Type guard

var prepErr *uow.BootstrapPreparationError
if errors.As(err, &prepErr) && prepErr.Retryable { /* transient: safe to retry */ }

Try / catch

err := provider.Open(ctx, cfg)
if err != nil {
    var prepErr *uow.BootstrapPreparationError
    if errors.As(err, &prepErr) {
        return retryWithBackoff(ctx, func() error { return provider.Open(ctx, cfg) })
    }
    return err
}

Prevention

When it happens

Trigger: During provider open, schema.MigrateUpWithLock's locked-preparation callback (bootstrapPreparer.prepare) returns a *bootstrapPreparationError with retryable=true; classifyInitSchemaError re-wraps it so the backoff retry in initSchema continues after the transient failure.

Common situations: Concurrent bd processes bootstrapping the same Dolt database at cold start; a peer holding the migration lock; brief connection blips to a loaded shared Dolt SQL server during CREATE DATABASE/USE.

Related errors


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