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

  1. Unwrap the error: if it contains 'identifier too long' or 'invalid identifier', fix the database name; otherwise treat it as a server/connection problem.
  2. Validate the name first with db.ValidateIdentifier and shorten/sanitize it.
  3. If the cause is a driver error, check connectivity and that the DB user has CREATE privileges.
  4. 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

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


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