gastownhall/beads · warning

flush: failed to open connection

Error message

flush: failed to open connection: %w

What it means

FlushWorkingSet wraps sql.Open("mysql", dsn) failure with this message when preparing its best-effort connection (as root, no password) to the running dolt server before shutdown. As with all sql.Open errors, this indicates a malformed DSN or unregistered driver, not an unreachable server — the ping step handles reachability separately. The function is best-effort: callers only log a warning if it fails.

Solutions

  1. Inspect the wrapped error for 'invalid DSN' and correct the host value in bd config (alphanumeric hostname or IP only)
  2. Validate BEADS_DB_HOST / dolt.shared-server-host has no stray quotes, spaces, or scheme (no 'http://')
  3. If building a custom binary, ensure _ "github.com/go-sql-driver/mysql" is imported
  4. This is best-effort (uncommitted working-set changes may be lost); if it persists, commit work manually before bd dolt stop
  5. Retry the stop/restart — the failure may come from transient config reload

Example fix

// before: scheme in host corrupts the DSN
// host := "http://127.0.0.1"
// after: plain host only
host := "127.0.0.1"
Defensive patterns

Strategy: validation

Validate before calling

// Validate host is a clean hostname/IP before FlushWorkingSet builds its DSN
if net.ParseIP(host) == nil {
    if _, err := net.LookupHost(host); err != nil {
        return fmt.Errorf("configured dolt host %q is not a valid host", host)
    }
}
if strings.ContainsAny(host, "@:/() \t") {
    return fmt.Errorf("configured dolt host %q contains invalid DSN characters", host)
}

Try / catch

if err := doltserver.FlushWorkingSet(host, port); err != nil {
    // best-effort by design: log and continue shutdown, but flag possible data loss
    log.Printf("warning: working-set flush skipped (%v); uncommitted changes may remain", err)
}

Prevention

When it happens

Trigger: sql.Open("mysql", dsn) errors while building the root/no-password DSN from host and port — invalid characters in the configured host, or the mysql driver missing from the binary.

Common situations: A hand-edited config leaving stray characters in dolt.host; custom builds without the go-sql-driver/mysql import; automated tooling injecting malformed host values.

Related errors


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

Appendix: source

Thrown at internal/doltserver/doltserver.go:1575

	return nil
}

// FlushWorkingSet connects to the running Dolt server and commits any uncommitted
// working set changes across all databases. This prevents data loss when the server
// is about to be stopped or restarted. Returns nil if there's nothing to flush or
// if the server is not reachable (best-effort).
func FlushWorkingSet(host string, port int) error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	dsn := doltutil.ServerDSN{
		Host: host,
		Port: port,
		User: "root",
	}.String()
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return fmt.Errorf("flush: failed to open connection: %w", err)
	}
	defer db.Close()
	db.SetMaxOpenConns(1)
	db.SetConnMaxLifetime(10 * time.Second)

	if err := db.PingContext(ctx); err != nil {
		return fmt.Errorf("flush: server not reachable: %w", err)
	}

	// List all databases, skipping system databases
	rows, err := db.QueryContext(ctx, "SHOW DATABASES")
	if err != nil {
		return fmt.Errorf("flush: failed to list databases: %w", err)
	}
	var databases []string
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {

View on GitHub (pinned to 71377f2769)