gastownhall/beads · error

uow: open db: %w

Error message

uow: open db: %w

What it means

openDB opens a database/sql connection to the Dolt SQL server using the mysql driver. This error wraps a failure returned by sql.Open itself. It is thrown when the DSN is malformed or the mysql driver cannot be initialized — before any network contact is made (sql.Open does not connect; failures here are configuration/driver-level, not connectivity).

Source

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

	return b.heal, nil
}

func buildDSN(ep proxy.Endpoint, database, user, password, tlsConfigName string) string {
	return util.DoltServerDSN{
		Host:            ep.Host,
		Port:            ep.Port,
		User:            user,
		Password:        password,
		Database:        database,
		TLSConfigName:   tlsConfigName,
		ClientFoundRows: true,
	}.String()
}

func openDB(ctx context.Context, dsn string) (*sql.DB, error) {
	conn, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, fmt.Errorf("uow: open db: %w", err)
	}
	if err := conn.PingContext(ctx); err != nil {
		return nil, errors.Join(fmt.Errorf("uow: ping db: %w", err), conn.Close())
	}
	return conn, nil
}

func openAndInitSchema(ctx context.Context, ep proxy.Endpoint, database, rootUser, rootPassword, tlsConfigName string, teamServer bool, expectedProjectID string, opts providerOptions) (UnitOfWorkProvider, error) {
	initDB, err := openDB(ctx, buildDSN(ep, "", rootUser, rootPassword, tlsConfigName))
	if err != nil {
		return nil, err
	}

	initProvider := &doltSQLProvider{
		defaultBranch:     defaultBranch,
		db:                initDB,
		serverEndpoint:    "tcp:" + ep.Address(),
		teamServer:        teamServer,

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the endpoint/user/password/TLS settings feeding buildDSN; escape special characters (e.g. '@', ':', '/', '(' in passwords) or use the go-sql-driver URL form.
  2. Verify the Dolt server endpoint uses host:port format (e.g. tcp:localhost:3306).
  3. Rebuild with the go-sql-driver/mysql driver registered (blank import present) if using a custom build.
  4. Print/log the constructed DSN (redacting password) to spot malformed fields.

Example fix

// before: unescaped password breaks DSN
password = "p@ss:word"
// after: escape or URL-encode special characters in credentials
password = "p%40ss%3Aword"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate endpoint and credentials before calling the library
func validateEndpoint(ep string) error {
    host, port, err := net.SplitHostPort(strings.TrimPrefix(ep, "tcp:"))
    if err != nil || host == "" || port == "" {
        return fmt.Errorf("invalid endpoint %q, want host:port", ep)
    }
    return nil
}
// Reject DSN-breaking characters in credentials
if strings.ContainsAny(password, "@:/()") {
    return fmt.Errorf("password contains characters requiring DSN escaping")
}

Type guard

func isOpenDBError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "uow: open db:")
}

Try / catch

p, err := uow.Open(ctx, cfg)
if err != nil {
    if strings.Contains(err.Error(), "uow: open db:") {
        return fmt.Errorf("bad DSN/config (check endpoint, escaping of user/password/TLS name): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: sql.Open("mysql", dsn) returns a non-nil error — typically an unparsable DSN produced by buildDSN (bad characters in host, user, password, database, or TLS config name) or unregistered "mysql" driver.

Common situations: Endpoint config containing characters that break DSN escaping (special chars in password without escaping); wrong endpoint format in bd config; binary built without the mysql driver import (rare).

Related errors


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