geektutu/7days-golang · error
rpc discovery: no available servers
Error message
rpc discovery: no available servers
What it means
Guard in MultiServersDiscovery.Get: the discovery instance's server list is empty (n == 0), so no peer can be selected under any SelectMode. It fires when Update was never called or the known set of servers shrank to nothing.
Source
Thrown at gee-rpc/day6-load-balance/xclient/discovery.go:55
func (d *MultiServersDiscovery) Refresh() error {
return nil
}
// Update the servers of discovery dynamically if needed
func (d *MultiServersDiscovery) Update(servers []string) error {
d.mu.Lock()
defer d.mu.Unlock()
d.servers = servers
return nil
}
// Get a server according to mode
func (d *MultiServersDiscovery) Get(mode SelectMode) (string, error) {
d.mu.Lock()
defer d.mu.Unlock()
n := len(d.servers)
if n == 0 {
return "", errors.New("rpc discovery: no available servers")
}
switch mode {
case RandomSelect:
return d.servers[d.r.Intn(n)], nil
case RoundRobinSelect:
s := d.servers[d.index%n] // servers could be updated, so mode n to ensure safety
d.index = (d.index + 1) % n
return s, nil
default:
return "", errors.New("rpc discovery: not supported select mode")
}
}
// returns all servers in discovery
func (d *MultiServersDiscovery) GetAll() ([]string, error) {
d.mu.RLock()
defer d.mu.RUnlock()
// return a copy of d.serversView on GitHub (pinned to cf36443821)
Solutions
- Ensure at least one server address is passed to NewMultiServersDiscovery or registered in the registry before creating the client.
- Guard calls: check len(discovery.GetAll()) > 0 before dialing, and retry after discovery refresh.
- Start the target servers so the registry has instances to report.
Example fix
// before
d := xclient.NewMultiServersDiscovery(nil)
xc := xclient.NewXDClient(d, xclient.RandomSelect)
// after
d := xclient.NewMultiServersDiscovery([]string{"tcp@127.0.0.1:9001", "tcp@127.0.0.1:9002"})
xc := xclient.NewXDClient(d, xclient.RandomSelect) Defensive patterns
Strategy: fallback
Validate before calling
servers, _ := d.GetAll()
if len(servers) == 0 {
// skip selection, fall back to direct address or retry after refresh
} Try / catch
addr, err := d.Get(mode)
if err != nil && err.Error() == "rpc discovery: no available servers" {
time.Sleep(500 * time.Millisecond) // allow discovery refresh
addr, err = d.Get(mode)
} Prevention
- Bootstrap discovery with at least one static address as a fallback.
- Start servers and confirm registry entries before launching clients.
- Monitor GetAll() size and alert when it drops to zero.
When it happens
Trigger: Creating MultiServersDiscovery with an empty address list, or the server list being emptied by Remove()/Update() before the first Get(), then calling Get(RandomSelect|RoundRobinSelect) via xclient.
Common situations: Registry returned no instances for a service (nothing registered yet), config file with an empty servers array, all peers removed during failure handling, or a race where discovery refreshes an empty list while requests are in flight.
Related errors
- rpc discovery: not supported select mode
- connection is shut down
- reading body
- rpc client: call failed:
- number of options is more than 1
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/cdd05a870d2fff0e.
Report an issue: GitHub.