{"record":{"id":"cdd05a870d2fff0e","repo":"geektutu/7days-golang","slug":"rpc-discovery-no-available-servers","errorCode":null,"errorMessage":"rpc discovery: no available servers","messagePattern":"rpc discovery: no available servers","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day6-load-balance/xclient/discovery.go","lineNumber":55,"sourceCode":"func (d *MultiServersDiscovery) Refresh() error {\n\treturn nil\n}\n\n// Update the servers of discovery dynamically if needed\nfunc (d *MultiServersDiscovery) Update(servers []string) error {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\td.servers = servers\n\treturn nil\n}\n\n// Get a server according to mode\nfunc (d *MultiServersDiscovery) Get(mode SelectMode) (string, error) {\n\td.mu.Lock()\n\tdefer d.mu.Unlock()\n\tn := len(d.servers)\n\tif n == 0 {\n\t\treturn \"\", errors.New(\"rpc discovery: no available servers\")\n\t}\n\tswitch mode {\n\tcase RandomSelect:\n\t\treturn d.servers[d.r.Intn(n)], nil\n\tcase RoundRobinSelect:\n\t\ts := d.servers[d.index%n] // servers could be updated, so mode n to ensure safety\n\t\td.index = (d.index + 1) % n\n\t\treturn s, nil\n\tdefault:\n\t\treturn \"\", errors.New(\"rpc discovery: not supported select mode\")\n\t}\n}\n\n// returns all servers in discovery\nfunc (d *MultiServersDiscovery) GetAll() ([]string, error) {\n\td.mu.RLock()\n\tdefer d.mu.RUnlock()\n\t// return a copy of d.servers","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day6-load-balance/xclient/discovery.go#L37-L73","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nd := xclient.NewMultiServersDiscovery(nil)\nxc := xclient.NewXDClient(d, xclient.RandomSelect)\n// after\nd := xclient.NewMultiServersDiscovery([]string{\"tcp@127.0.0.1:9001\", \"tcp@127.0.0.1:9002\"})\nxc := xclient.NewXDClient(d, xclient.RandomSelect)","handlingStrategy":"fallback","validationCode":"servers, _ := d.GetAll()\nif len(servers) == 0 {\n    // skip selection, fall back to direct address or retry after refresh\n}","typeGuard":null,"tryCatchPattern":"addr, err := d.Get(mode)\nif err != nil && err.Error() == \"rpc discovery: no available servers\" {\n    time.Sleep(500 * time.Millisecond) // allow discovery refresh\n    addr, err = d.Get(mode)\n}","preventionTips":["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."],"tags":["rpc","discovery","load-balance","empty-server-list"],"backgroundTag":"no-servers-available","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}