gastownhall/beads · error
db: CreateDatabaseIfNotExists: %w
Error message
db: CreateDatabaseIfNotExists: %w
What it means
CreateDatabaseIfNotExists wraps two distinct failures under the same prefix: an identifier validation failure from QuoteIdentifier (bad database name), and a driver failure from executing `CREATE DATABASE IF NOT EXISTS <ident>` (connection issues, insufficient privileges, server errors). Unwrap the error to distinguish which one occurred — the %w chain preserves the cause.
Source
Thrown at internal/storage/domain/db/ddl.go:49
// classify it against their driver.
CreateDatabase(ctx context.Context, database string) error
UseDatabase(ctx context.Context, database string) error
}
func NewDDLSQLRepository(runner Runner) DDLSQLRepository {
return &ddlSQLRepository{runner: runner}
}
type ddlSQLRepository struct {
runner Runner
}
var _ DDLSQLRepository = (*ddlSQLRepository)(nil)
func (r *ddlSQLRepository) CreateDatabaseIfNotExists(ctx context.Context, database string) error {
ident, err := quoteIdentifier(database)
if err != nil {
return fmt.Errorf("db: CreateDatabaseIfNotExists: %w", err)
}
if _, err := r.runner.ExecContext(ctx, "CREATE DATABASE IF NOT EXISTS "+ident); err != nil {
return fmt.Errorf("db: CreateDatabaseIfNotExists: %w", err)
}
return nil
}
func (r *ddlSQLRepository) CreateDatabase(ctx context.Context, database string) error {
ident, err := quoteIdentifier(database)
if err != nil {
return fmt.Errorf("db: CreateDatabase: %w", err)
}
if _, err := r.runner.ExecContext(ctx, "CREATE DATABASE "+ident); err != nil {
return fmt.Errorf("db: CreateDatabase: %w", err)
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error: if it contains 'identifier too long' or 'invalid identifier', fix the database name; otherwise treat it as a server/connection problem.
- Validate the name first with db.ValidateIdentifier and shorten/sanitize it.
- If the cause is a driver error, check connectivity and that the DB user has CREATE privileges.
- Retry after fixing the name or restoring server access.
Example fix
// before
name := os.Getenv("BD_DB") // could be empty or contain hyphens
err := ddl.CreateDatabaseIfNotExists(ctx, name)
// after
name := os.Getenv("BD_DB")
if err := db.ValidateIdentifier(name); err != nil {
return fmt.Errorf("bad BD_DB %q: %w", name, err)
}
err := ddl.CreateDatabaseIfNotExists(ctx, name) Defensive patterns
Strategy: validation
Validate before calling
if err := db.ValidateIdentifier(database); err != nil {
return fmt.Errorf("cannot create database %q: %w", database, err)
}
if err := conn.PingContext(ctx); err != nil {
return fmt.Errorf("cannot create database: server unreachable: %w", err)
} Type guard
func canCreate(name string) bool {
return db.ValidateIdentifier(name) == nil
} Try / catch
err := ddl.CreateDatabaseIfNotExists(ctx, name)
if err != nil {
if vErr := db.ValidateIdentifier(name); vErr != nil {
return fmt.Errorf("bad name: %w", vErr)
}
return fmt.Errorf("server rejected CREATE DATABASE: %w", err) // privilege/connection issue
} Prevention
- Always validate the name with db.ValidateIdentifier before CreateDatabaseIfNotExists to separate name errors from server errors.
- Ensure the DB user has CREATE privileges in the target deployment.
- Check server reachability during bootstrap before attempting DDL.
- Derive database names from sanitized, bounded-length inputs.
When it happens
Trigger: Calling CreateDatabaseIfNotExists with an invalid database name (too long or illegal characters), or when the CREATE DATABASE statement fails on the server — no connection, missing CREATE privilege, or a server-side error.
Common situations: Bootstrap/initialization flows creating a workspace database with a misconfigured name; connecting as a user lacking CREATE privileges; database server unreachable during first run; names over 64 chars or containing hyphens.
Related errors
- db: Exists: id must not be empty
- db: CountForPrefix: prefix must not be empty
- db: NextCounterID: prefix must not be empty
- database name too long
- invalid database name: %s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d4c65d0d4825c71f.
Report an issue: GitHub.