{"record":{"id":"2d4e0ba1646d6d22","repo":"grpc/grpc-go","slug":"all-subconns-are-in-transientfailure-last-connect","errorCode":null,"errorMessage":"all SubConns are in TransientFailure, last connection error: %v","messagePattern":"all SubConns are in TransientFailure, last connection error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"balancer/grpclb/grpclb.go","lineNumber":249,"sourceCode":"\tremoteBalancerConnected bool\n\tserverListReceived      bool\n\tinFallback              bool\n\t// resolvedBackendAddrs is resolvedAddrs minus remote balancers. It's set\n\t// when resolved address updates are received, and read in the goroutine\n\t// handling fallback.\n\tresolvedBackendAddrs []resolver.Address\n\tconnErr              error // the last connection error\n}\n\n// regeneratePicker takes a snapshot of the balancer, and generates a picker from\n// it. The picker\n//   - always returns ErrTransientFailure if the balancer is in TransientFailure,\n//   - does two layer roundrobin pick otherwise.\n//\n// Caller must hold lb.mu.\nfunc (lb *lbBalancer) regeneratePicker(resetDrop bool) {\n\tif lb.state == connectivity.TransientFailure {\n\t\tlb.picker = base.NewErrPicker(fmt.Errorf(\"all SubConns are in TransientFailure, last connection error: %v\", lb.connErr))\n\t\treturn\n\t}\n\n\tif lb.state == connectivity.Connecting {\n\t\tlb.picker = base.NewErrPicker(balancer.ErrNoSubConnAvailable)\n\t\treturn\n\t}\n\n\tvar readySCs []balancer.SubConn\n\tif lb.usePickFirst {\n\t\tfor _, sc := range lb.subConns {\n\t\t\treadySCs = append(readySCs, sc)\n\t\t\tbreak\n\t\t}\n\t} else {\n\t\tfor _, a := range lb.backendAddrsWithoutMetadata {\n\t\t\tif sc, ok := lb.subConns[a]; ok {\n\t\t\t\tif st, ok := lb.scStates[sc]; ok && st == connectivity.Ready {","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/balancer/grpclb/grpclb.go#L231-L267","documentation":"Produced by grpclb's regeneratePicker when the gRPC-LB balancer is in TransientFailure: every SubConn to the backends selected by the remote balancer has failed, so the picker returns this error on every Pick. The wrapped %v is lb.connErr, the last connection error from the failing SubConns. The RPC fails with Unavailable carrying this message.","triggerScenarios":"Using the grpclb:// scheme (delegating to a remote load balancer) and all backend SubConns created from the server list are in TransientFailure. regeneratePicker's first branch fires.","commonSituations":"The remote balancer returned a server list whose backends are all unreachable; TLS/auth to backends is misconfigured; the backends crashed but the remote balancer hasn't updated its list; network partition between client and backend pool.","solutions":["Read the wrapped connection error %v (refused, TLS, timeout) and fix that layer.","Verify the remote load balancer is returning healthy backend addresses (check the balancer's admin/API).","Confirm grpclb fallback is configured if you want to fall back to resolved addresses when the remote list is bad.","Note: grpclb is deprecated in favor of xDS; consider migrating if this is recurring."],"exampleFix":"// before: all backends refused due to wrong port in remote balancer config\n// error: 'all SubConns are in TransientFailure, last connection error: dial tcp: connect: connection refused'\n\n// after: correct the backend port in the remote load balancer's server list so SubConns reach READY","handlingStrategy":"retry","validationCode":"// grpclb: pre-flight one of the backends from the remote balancer's list\n// (or a fallback address) before relying on the channel.\nfunc checkGrpcLbBackend(addr string) error {\n    return checkDial(addr, 2*time.Second) // from error 93\n}","typeGuard":null,"tryCatchPattern":"// All SubConns in TransientFailure -> Unavailable. Retry idempotent RPCs\n// and consider switching off grpclb if it recurs (grpclb is deprecated).\nfor i := 0; i < maxRetries; i++ {\n    err := stub.Do(ctx, req)\n    if err == nil { return nil }\n    if status.Code(err) != codes.Unavailable { return err }\n    select { case <-time.After(backoffFor(i)): case <-ctx.Done(): return ctx.Err() }\n}","preventionTips":["Plan a migration off grpclb to xDS (grpclb is deprecated).","Verify the remote balancer's server list points at healthy backends.","Configure grpclb fallback to resolved addresses.","Monitor backend SubConn states via channelz."],"tags":["balancer","grpclb","transient-failure","connection","runtime","network","deprecated"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}