geektutu/7days-golang · error

rpc client: connect timeout: expect within %s

Error message

rpc client: connect timeout: expect within %s

What it means

Day7-registry dialTimeout: with opt.ConnectTimeout > 0, if the async dial + options handshake does not complete in time, this timeout error is returned while the background attempt is abandoned. ConnectTimeout == 0 disables the deadline (blocks until result).

Source

Thrown at gee-rpc/day7-registry/client.go:273

	}
	// close the connection if client is nil
	defer func() {
		if err != nil {
			_ = conn.Close()
		}
	}()
	ch := make(chan clientResult)
	go func() {
		client, err := f(conn, opt)
		ch <- clientResult{client: client, err: err}
	}()
	if opt.ConnectTimeout == 0 {
		result := <-ch
		return result.client, result.err
	}
	select {
	case <-time.After(opt.ConnectTimeout):
		return nil, fmt.Errorf("rpc client: connect timeout: expect within %s", opt.ConnectTimeout)
	case result := <-ch:
		return result.client, result.err
	}
}

// Dial connects to an RPC server at the specified network address
func Dial(network, address string, opts ...*Option) (*Client, error) {
	return dialTimeout(NewClient, network, address, opts...)
}

// NewHTTPClient new a Client instance via HTTP as transport protocol
func NewHTTPClient(conn net.Conn, opt *Option) (*Client, error) {
	_, _ = io.WriteString(conn, fmt.Sprintf("CONNECT %s HTTP/1.0\n\n", defaultRPCPath))

	// Require successful HTTP response
	// before switching to RPC protocol.
	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {

View on GitHub (pinned to cf36443821)

Solutions

  1. Confirm the target address from the registry is alive; refresh/fix registry entries.
  2. Raise opt.ConnectTimeout (DefaultOption uses 5s) in the passed Option.
  3. Investigate network connectivity; retry after the server recovers.

Example fix

// before
client, err := geerpc.XDial("tcp@10.0.0.1:9999") // 5s default too short
// after
opt := geerpc.DefaultOption
opt.ConnectTimeout = 15 * time.Second
client, err := geerpc.XDial("tcp@10.0.0.1:9999", opt)
Defensive patterns

Strategy: retry

Validate before calling

opt := geerpc.DefaultOption
opt.ConnectTimeout = 15 * time.Second
// pre-flight check against registry-selected addresses:
if _, err := net.DialTimeout("tcp", addr, 3*time.Second); err != nil {
    // pick another server from the registry
}

Try / catch

client, err := geerpc.XDial("tcp@"+addr, opt)
if err != nil {
    if strings.Contains(err.Error(), "connect timeout") {
        client, err = dialWithRetry(addr, opt, 3) // exponential backoff
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Dial/DialHTTP/XDial to a dead, wrong, or slow endpoint exceeding ConnectTimeout; the heart-beat-enabled server is down; an anonymous goroutine dial (via registry-selected server) fails to finish in time.

Common situations: Registry returning stale server addresses; server crashed between registry registration and dial; tight ConnectTimeout in production configs; network partitions.

Understand the failure class

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/fb3bccace138d8b1. Report an issue: GitHub.