gastownhall/beads · error · bootstrapPreparationError
uow: creating database: %w
Error message
uow: creating database: %w
What it means
This error is produced by bootstrapPreparer.prepare when the sticky re-assert path (b.created already true from a prior attempt) calls CreateDatabaseIfNotExists and the CREATE IF NOT EXISTS fails for a non-serialization reason. It is wrapped in a bootstrapPreparationError without retryable=true, so it is terminal for the initSchema backoff loop. This path exists so a database dropped between attempts (e.g. concurrent clean-databases) is recreated rather than failing the subsequent USE.
Source
Thrown at internal/storage/uow/dolt_sql_provider.go:327
// never inferred again from probing or CREATE IF NOT EXISTS.
created bool
// heal is the one-shot capability captured in the CREATE-winning attempt and
// re-returned unchanged on later attempts.
heal *schema.FreshBootstrapHealCapability
}
// prepare is MigrateUpWithLock's locked-preparation callback. It (re)creates and
// selects the target database and, only in the attempt that won the bare CREATE,
// captures the fresh-bootstrap heal capability. See bootstrapPreparer.
func (b *bootstrapPreparer) prepare(ctx context.Context, conn *sql.Conn) (*schema.FreshBootstrapHealCapability, error) {
ddl := db.NewDDLSQLRepository(conn)
justCreated := false
if b.created {
// Re-assert on retries so a database dropped between attempts
// (e.g. a concurrent clean-databases) is recreated rather than
// failing the USE below.
if err := ddl.CreateDatabaseIfNotExists(ctx, b.database); err != nil {
return nil, &bootstrapPreparationError{err: fmt.Errorf("uow: creating database: %w", err)}
}
} else {
switch err := ddl.CreateDatabase(ctx, b.database); {
case err == nil:
b.created = true
justCreated = true
case isDatabaseExistsError(err):
// Pre-existing (or a concurrent initializer won the create
// race): not ours, heal stays off.
case isSerializationError(err):
// Only the initial bare CREATE preserves its historical
// serialization retry classification. The later sticky CREATE,
// USE, and identity capture remain permanent regardless of
// their nested driver error.
return nil, &bootstrapPreparationError{
err: fmt.Errorf("uow: creating database: %w", err),
retryable: true,
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error for the root cause and fix it — commonly granting the connecting user CREATE privilege on the server.
- Verify the configured database name is valid and that the server endpoint accepts DDL (not a read-only replica).
- Stop any concurrent clean-databases / dropping job racing with bd init, then re-run the command.
- Check connectivity to the Dolt server and re-run init.
Example fix
// before (insufficient privilege) CREATE DATABASE IF NOT EXISTS beads_ws; -- ERROR 1044: access denied // after (as server admin) GRANT CREATE, ALTER ON `beads_ws`.* TO 'beads'@'%'; FLUSH PRIVILEGES;
Defensive patterns
Strategy: validation
Validate before calling
// Verify the connecting user can create databases BEFORE running init:
var unused string
if err := conn.QueryRowContext(ctx, "SELECT 1").Err(); err != nil { return err }
// Probe DDL privilege on the server (server-appropriate check) or confirm grants:
// SHOW GRANTS FOR CURRENT_USER; must include CREATE privilege.
if err := checkCreatePrivilege(ctx, conn); err != nil {
return fmt.Errorf("bootstrap requires CREATE privilege: %w", err)
} Type guard
func isPermanentPreparation(err error) bool {
var bpe *bootstrapPreparationError
return errors.As(err, &bpe) && !bpe.retryable
} Try / catch
if err := bdInit(ctx); err != nil {
var bpe *bootstrapPreparationError
if errors.As(err, &bpe) && !bpe.retryable {
log.Fatalf("terminal database creation failure: %v — check grants/DDL permissions", bpe.err)
}
return err // retryable path handled by backoff
} Prevention
- Grant the bd user CREATE (and ALTER) privileges on the target database before first init.
- Validate the database name against server naming rules in configuration.
- Ensure the Dolt server endpoint accepts DDL (not a read-only replica or restricted proxy).
- Avoid scheduling clean-databases jobs that drop databases while clients are bootstrapping.
- Test connectivity to the Dolt server before running init in CI.
When it happens
Trigger: A retry attempt of initSchema whose CREATE already succeeded earlier (b.created sticky), but the re-assert CREATE DATABASE IF NOT EXISTS fails — e.g. permission denied for CREATE, invalid database name/charset, server refusing DDL, or connection dropped mid-DDL with a non-serialization error.
Common situations: Database credentials lacking CREATE privilege after an ACL change; server-side DDL restrictions or read-only replica; database name violating server naming rules; concurrent process actively dropping databases while init retries; network interruption to a remote Dolt server.
Related errors
- failed to create dolt directory: %w
- dolt path is not executable
- database %q not found on Dolt server at %s:%d
- commit import: %w
- create beads directory: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e7309063438b50d3.
Report an issue: GitHub.