grpc/grpc-go · error

all SubConns are in TransientFailure

Error message

all SubConns are in TransientFailure

What it means

Deprecated sentinel (balancer.ErrTransientFailure) a Picker returns when every SubConn is in TransientFailure. Per balancer/balancer.go:269-275 and :330-332, WaitForReady RPCs block while non-WaitForReady RPCs are terminated with status Unavailable carrying this message. The doc comment explicitly tells balancer authors to instead return an appropriate error based on the last resolution/connection attempt; behavior for any non-gRPC-status error is identical, so the sentinel is redundant.

Source

Thrown at balancer/balancer.go:275

	BytesReceived bool
	// ServerLoad is the load received from server. It's usually sent as part of
	// trailing metadata.
	//
	// The only supported type now is *orca_v3.LoadReport.
	ServerLoad any
}

var (
	// ErrNoSubConnAvailable indicates no SubConn is available for pick().
	// gRPC will block the RPC until a new picker is available via UpdateState().
	ErrNoSubConnAvailable = errors.New("no SubConn is available")
	// ErrTransientFailure indicates all SubConns are in TransientFailure.
	// WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
	//
	// Deprecated: return an appropriate error based on the last resolution or
	// connection attempt instead.  The behavior is the same for any non-gRPC
	// status error.
	ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
)

// PickResult contains information related to a connection chosen for an RPC.
type PickResult struct {
	// SubConn is the connection to use for this pick, if its state is Ready.
	// If the state is not Ready, gRPC will block the RPC until a new Picker is
	// provided by the balancer (using ClientConn.UpdateState).  The SubConn
	// must be one returned by ClientConn.NewSubConn.
	SubConn SubConn

	// Done is called when the RPC is completed.  If the SubConn is not ready,
	// this will be called with a nil parameter.  If the SubConn is not a valid
	// type, Done may not be called.  May be nil if the balancer does not wish
	// to be notified when the RPC completes.
	Done func(DoneInfo)

	// Metadata provides a way for LB policies to inject arbitrary per-call
	// metadata. Any metadata returned here will be merged with existing

View on GitHub (pinned to 03255a9237)

Solutions

  1. Inspect cc.connectionError() / the last subchannel error to find the real cause (TLS, DNS, refused) — the TransientFailure message itself is not diagnostic.
  2. Fix the root backend/network issue so at least one SubConn reaches READY.
  3. If you maintain a Picker, stop returning ErrTransientFailure; wrap the most recent connection attempt error (e.g. status.Errorf(codes.Unavailable, '%v', lastErr)).
  4. Use grpc.WaitForReady(true) with a deadline if you want RPCs to ride through transient outages.

Example fix

// before (custom picker)
return balancer.PickResult{}, balancer.ErrTransientFailure

// after
return balancer.PickResult{}, status.Errorf(codes.Unavailable, "last conn error: %v", lastConnErr)
Defensive patterns

Strategy: retry

Validate before calling

// Treat TransientFailure as recoverable; check real cause
if cc.GetState() == connectivity.TransientFailure {
    if e := cc.connectionError(); e != nil { log.Println("root cause:", e) }
}

Try / catch

if errors.Is(err, balancer.ErrTransientFailure) || status.Code(err) == codes.Unavailable {
    // back off and retry; consult connectionError() for the real cause
}

Prevention

When it happens

Trigger: A Picker returns balancer.ErrTransientFailure (or any non-status error with the same semantics) after the connectivity evaluator reports TransientFailure for all subchannels — i.e. every backend connection attempt failed (TCP refused, TLS handshake error, auth failure) and the LB policy aggregated to TransientFailure.

Common situations: All backends down or unreachable; TLS trust chain broken so every handshake fails; the wrong target/authority so connections are refused; a custom balancer still using the deprecated sentinel instead of the last connection error.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/9abc69b90e1b2e60. Report an issue: GitHub.