grpc/grpc-go · error
name resolver error
Error message
name resolver error: %v
What it means
Produced by pickfirst's resolverErrorLocked() (balancer/pickfirst/pickfirst.go:206). The picker wraps this error when the balancer transitions to TransientFailure because the name resolver produced an error and there is no usable previous address list to fall back on (addressList.size() == 0 or state is already TransientFailure). It means name resolution failed and the channel has no addresses to try.
Solutions
- Inspect the embedded resolver error (%v) — it is the concrete cause (DNS error, xDS error, etc.).
- Verify the target URI / service name is correct and resolvable.
- If using DNS, confirm the DNS server is reachable and returns records.
- If using xDS, verify the EDS/CDS resources are present and non-empty.
Example fix
// before: unresolvable target name
conn, _ := grpc.NewClient("dns:///nonexistent-host:50051", grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"pick_first":{}}]}`))
// after: valid resolvable target
conn, _ := grpc.NewClient("dns:///real-svc.default.svc.cluster.local:50051", grpc.WithDefaultServiceConfig(`{"loadBalancingConfig":[{"pick_first":{}}]}`)) Defensive patterns
Strategy: retry
Try / catch
// Name resolver error → Unavailable. Retry; the channel re-resolves.
for {
resp, err := c.Call(ctx, in, grpc.WaitForReady(true))
if err == nil { return resp, nil }
if status.Code(err) != codes.Unavailable { return nil, err }
select {
case <-time.After(backoff):
case <-ctx.Done(): return nil, ctx.Err()
}
} Prevention
- Validate the target URI is resolvable at deploy time.
- Monitor resolver error rates (DNS, xDS) separately from connection errors.
- Provide a fallback resolver or cache the last good address list.
When it happens
Trigger: The resolver reports an error via ResolverError(), and either the balancer never received a good update (addressList.size() == 0, line 197) or the balancer is already in TransientFailure. The picker is set at line 204-207 to report 'name resolver error: <err>'. This also fires when UpdateClientConnState receives zero addresses (line 219) which calls resolverErrorLocked.
Common situations: DNS resolution fails (NXDOMAIN, DNS server unreachable); the target URI is malformed; an xDS resolver returns no endpoints and no prior good list exists; the service name is wrong; the resolver implementation throws.
Related errors
- last connection error
- all SubConns are in TransientFailure, last connection error
- last connection error
- last resolver error
- pickfirst: health check failure
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/7ac9df03ec4f2ba5.
Report an issue: GitHub.
Appendix: source
Thrown at balancer/pickfirst/pickfirst.go:206
func (b *pickfirstBalancer) resolverErrorLocked(err error) {
if b.logger.V(2) {
b.logger.Infof("Received error from the name resolver: %v", err)
}
// The picker will not change since the balancer does not currently
// report an error. If the balancer hasn't received a single good resolver
// update yet, transition to TRANSIENT_FAILURE.
if b.state != connectivity.TransientFailure && b.addressList.size() > 0 {
if b.logger.V(2) {
b.logger.Infof("Ignoring resolver error because balancer is using a previous good update.")
}
return
}
b.updateBalancerState(balancer.State{
ConnectivityState: connectivity.TransientFailure,
Picker: &picker{err: fmt.Errorf("name resolver error: %v", err)},
})
}
func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error {
b.mu.Lock()
defer b.mu.Unlock()
b.cancelConnectionTimer()
if len(state.ResolverState.Addresses) == 0 && len(state.ResolverState.Endpoints) == 0 {
// Cleanup state pertaining to the previous resolver state.
// Treat an empty address list like an error by calling b.ResolverError.
b.closeSubConnsLocked()
b.addressList.updateAddrs(nil)
b.resolverErrorLocked(errors.New("produced zero addresses"))
return balancer.ErrBadResolverState
}
b.healthCheckingEnabled = state.ResolverState.Attributes.Value(enableHealthListenerKeyType{}) != nil
cfg, ok := state.BalancerConfig.(pfConfig)
if state.BalancerConfig != nil && !ok {View on GitHub (pinned to 0c51461d27)