gastownhall/beads · error

server: DoltServer.Dial: %w

Error message

server: DoltServer.Dial: %w

What it means

DoltServer.Dial dials the running Dolt server over TCP or a Unix socket and wraps any net.Dialer.DialContext failure. It surfaces the OS-level network error (connection refused, no such file, timeout) with the server: DoltServer.Dial prefix.

Source

Thrown at internal/storage/dbproxy/server/doltserver.go:427

	return retErr
}

func (s *DoltServer) Running(_ context.Context) bool {
	if s.egCtx == nil {
		return false
	}
	return s.egCtx.Err() == nil
}

func (s *DoltServer) Dial(ctx context.Context) (net.Conn, error) {
	network, addr := "tcp", net.JoinHostPort(s.config.Host(), strconv.Itoa(s.config.Port()))
	if sock := s.config.Socket(); sock != "" {
		network, addr = "unix", sock
	}
	var d net.Dialer
	conn, err := d.DialContext(ctx, network, addr)
	if err != nil {
		return nil, fmt.Errorf("server: DoltServer.Dial: %w", err)
	}
	if tc, ok := conn.(*net.TCPConn); ok {
		_ = tc.SetKeepAlive(true)
		_ = tc.SetKeepAlivePeriod(s.keepAlivePeriod)
	}
	return conn, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Confirm the server is Running and check its actual listening address (config.Port()/Socket()) matches what Dial uses
  2. Use waitReady with a generous retry/backoff instead of dialing immediately after Start
  3. For unix sockets, verify the socket file exists (os.Stat) and the path is < 108 chars with correct permissions
  4. Test connectivity directly: `nc -z localhost <port>` or `nc -U <socket>` to isolate OS-level failures

Example fix

// before
conn, err := server.Dial(ctx)
if err != nil { return err }
// after
err := waitReady(ctx, server, 30*time.Second) // retry dial until server listens
if err != nil { return fmt.Errorf("dolt server never became ready: %w", err) }
Defensive patterns

Strategy: retry

Validate before calling

// check reachability before Dial
addr := fmt.Sprintf("%s:%d", host, port)
if sock != "" {
    if _, err := os.Stat(sock); err != nil { return fmt.Errorf("socket %s missing: %w", sock, err) }
} else if conn, err := net.DialTimeout("tcp", addr, time.Second); err != nil {
    return fmt.Errorf("%s unreachable: %w", addr, err)
} else { conn.Close() }

Try / catch

var conn net.Conn
err := retry.Do(func() (err error) {
    conn, err = server.Dial(ctx)
    return err
}, retry.Delay(200*time.Millisecond), retry.Attempts(10), retry.Context(ctx))
if err != nil { return fmt.Errorf("dolt server not reachable: %w", err) }
defer conn.Close()

Prevention

When it happens

Trigger: Calling Dial (directly or via waitReady) when the server is not yet listening, the configured port/socket path is wrong, the socket file was deleted, or the context deadline expires before the TCP/socket handshake.

Common situations: Client dialing before the server finished starting (waitReady race), port already reassigned after a crash, socket path mismatch between config and caller, firewall or container network isolation blocking localhost TCP.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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