geektutu/7days-golang · error
rpc client: connect timeout: expect within %s
Error message
rpc client: connect timeout: expect within %s
What it means
dialTimeout in gee-rpc/day4-timeout enforces opt.ConnectTimeout on the asynchronous dial handshake. If the connection is not established (and options not exchanged) within that window, it returns "rpc client: connect timeout: expect within %s" and abandons the attempt even though the goroutine may still complete later.
Source
Thrown at gee-rpc/day4-timeout/client.go:269
}
// 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...)
}
View on GitHub (pinned to cf36443821)
Solutions
- Increase opt.ConnectTimeout to comfortably exceed worst-case connect + options-exchange time
- Verify the server is running and reachable at the address (telnet/nc the port)
- Leave ConnectTimeout as 0 to disable the deadline and use the OS connect timeout
- Check for silent firewall drops between client and server
Example fix
// before
opt := &geerpc.Option{ConnectTimeout: 10 * time.Millisecond}
client, err := geerpc.Dial("tcp", "remote:9000", opt)
// after
opt := &geerpc.Option{ConnectTimeout: 3 * time.Second}
client, err := geerpc.Dial("tcp", "remote:9000", opt) Defensive patterns
Strategy: retry
Validate before calling
if opt.ConnectTimeout != 0 && opt.ConnectTimeout < 500*time.Millisecond {
return errors.New("ConnectTimeout too small; use >= 500ms or 0 to disable")
} Try / catch
client, err := geerpc.Dial("tcp", addr, opt)
if err != nil && strings.Contains(err.Error(), "connect timeout") {
time.Sleep(500 * time.Millisecond)
client, err = geerpc.Dial("tcp", addr, opt) // bounded retry
} Prevention
- Budget ConnectTimeout for DNS + TCP connect + the JSON options exchange
- Probe the server port before dialing in deployment scripts
- Use 0 (disabled) when connecting over slow or lossy networks
- Add bounded retries with backoff around Dial
When it happens
Trigger: Dial with an Option whose ConnectTimeout > 0 while net.Dial plus NewClient (option exchange) exceed the deadline — slow/unreachable host, DNS stall, firewalled port, or a ConnectTimeout set shorter than network RTT.
Common situations: Server not listening (port closed, firewall silently dropping); wrong address in tests/CI without the server up; ConnectTimeout of a few milliseconds in a latency-sensitive environment; server accepting TCP but never responding to the options header.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- rpc client: connect timeout: expect within %s
- %s
- rpc client: connect timeout: expect within %s
- rpc client: connect timeout: expect within %s
- connection is shut down
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/c3c8fe1cd91824d8.
Report an issue: GitHub.