{"record":{"id":"538e484258c8610a","repo":"go-kit/kit","slug":"no-endpoints-available","errorCode":null,"errorMessage":"no endpoints available","messagePattern":"no endpoints available","errorType":"exception","errorClass":"ErrNoEndpoints","httpStatus":503,"severity":"error","filePath":"sd/lb/balancer.go","lineNumber":15,"sourceCode":"package lb\n\nimport (\n\t\"errors\"\n\n\t\"github.com/go-kit/kit/endpoint\"\n)\n\n// Balancer yields endpoints according to some heuristic.\ntype Balancer interface {\n\tEndpoint() (endpoint.Endpoint, error)\n}\n\n// ErrNoEndpoints is returned when no qualifying endpoints are available.\nvar ErrNoEndpoints = errors.New(\"no endpoints available\")\n","sourceCodeStart":1,"sourceCodeEnd":16,"githubUrl":"https://github.com/go-kit/kit/blob/78fbbceece7bbcf073bee814a7772f4397ea756c/sd/lb/balancer.go#L1-L16","documentation":"Declared in sd/lb/balancer.go and returned by the RoundRobin (round_robin.go:29) and Random (random.go:29) balancers when the sd.Endpointer yields an empty endpoint slice: service discovery currently knows zero qualifying instances for the target service. The balancer has nothing to hand out, so Retry/RPC code that called balancer.Endpoint() gets this error instead of an endpoint.","triggerScenarios":"The service deregistered from (or never registered in) consul/etcd/zookeeper/dnssrv; the Instancer subscriber hasn't received its first update yet (startup race); all instances failed their health check and were pruned; the subscriber lost its connection to the discovery backend so its cache went empty; wrong service name queried.","commonSituations":"Cold start: consumer boots before any producer registers; discovery backend outage or credentials expiry; k8s scale-to-zero then a request arrives before scale-up; environment misconfiguration (wrong namespace/datacenter in the SD client); all endpoints marked unhealthy after a deploy gone wrong.","solutions":["Verify the service is registered and healthy in the discovery backend (consul members/catalog, etcd keys, DNS SRV record)","Use sd Retry with a backoff window so balancer.Endpoint() is re-attempted while discovery warms up","Check the Instancer/subscriber construction: correct service name, datacenter, and a working SD client connection","Expose the error as HTTP 503 (not 500) so callers and LBs treat it as temporary"],"exampleFix":"// before: single call, fails on cold start\nep, err := lb.NewRoundRobin(subscriber).Endpoint()\nif err != nil {\n\treturn err // lb.ErrNoEndpoints\n}\n\n// after: brief bounded retry while discovery populates\nvar ep endpoint.Endpoint\nfor i := 0; i < 5; i++ {\n\tep, err = balancer.Endpoint()\n\tif err == nil {\n\t\tbreak\n\t}\n\tif !errors.Is(err, lb.ErrNoEndpoints) {\n\t\treturn err\n\t}\n\ttime.Sleep(200 * time.Millisecond)\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"ep, err := balancer.Endpoint()\nif err != nil {\n\tif !errors.Is(err, lb.ErrNoEndpoints) {\n\t\treturn err // different failure, propagate\n\t}\n\t// discovery is empty: bounded retry with backoff, then surface as 503\n\tif err := retryWithBackoff(ctx, 5, 300*time.Millisecond, func() error {\n\t\tep, err = balancer.Endpoint()\n\t\treturn err\n\t}); err != nil {\n\t\treturn err\n\t}\n}","preventionTips":["Delay consumer readiness until the Instancer has received its first discovery update (liveness/readiness probes)","Wrap balancer.Endpoint() in sd/lb Retry so transient empty pools are retried automatically","Monitor the subscriber's endpoint count; alert when it drops to zero","Return 503 (not 500) for ErrNoEndpoints so upstream LBs and clients back off correctly"],"tags":["go","go-kit","service-discovery","load-balancing","startup"],"backgroundTag":null,"analyzedSha":"78fbbceece7bbcf073bee814a7772f4397ea756c","analyzedAt":"2026-08-15T22:31:35.570Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}