grpc/grpc-go · error

grpc: the connection is closing

Error message

grpc: the connection is closing

What it means

Internal sentinel errConnClosing (clientconn.go:73-74) surfaced when the ClientConn is being torn down or the dial context is cancelled. It is returned from exitIdleMode when cc.conns==nil (clientconn.go:394-396) and from tryAllAddrs when ctx.Err()!=nil (clientconn.go:1455-1456). The user-facing analogue is ErrClientConnClosing (status Canceled).

Source

Thrown at clientconn.go:74

	_ "google.golang.org/grpc/resolver/dns"                  // To register dns resolver.
)

const (
	// minimum time to give a connection to complete
	minConnectTimeout = 20 * time.Second
)

var (
	// ErrClientConnClosing indicates that the operation is illegal because
	// the ClientConn is closing.
	//
	// Deprecated: this error should not be relied upon by users; use the status
	// code of Canceled instead.
	ErrClientConnClosing = status.Error(codes.Canceled, "grpc: the client connection is closing")
	// errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs.
	errConnDrain = errors.New("grpc: the connection is drained")
	// errConnClosing indicates that the connection is closing.
	errConnClosing = errors.New("grpc: the connection is closing")
	// errConnIdling indicates the connection is being closed as the channel
	// is moving to an idle mode due to inactivity.
	errConnIdling = errors.New("grpc: the connection is closing due to channel idleness")
	// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default
	// service config.
	invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid"
	// PickFirstBalancerName is the name of the pick_first balancer.
	PickFirstBalancerName = pickfirst.Name
)

// The following errors are returned from Dial and DialContext
var (
	// errNoTransportSecurity indicates that there is no transport security
	// being set for ClientConn. Users should either set one or explicitly
	// call WithInsecure DialOption to disable security.
	errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)")
	// errTransportCredsAndBundle indicates that creds bundle is used together
	// with other individual Transport Credentials.

View on GitHub (pinned to 03255a9237)

Solutions

  1. Stop issuing RPCs on a ClientConn before/after Close(); treat Close as terminal — create a new ClientConn to reconnect.
  2. If you need ordered shutdown, wait for in-flight RPCs to finish (WaitGroup/context) before Close().
  3. When using DialContext, ensure the context outlives the dial (or pass context.Background() and rely on WithTimeout for the connect deadline).
  4. Map Canceled status (ErrClientConnClosing) at the application layer to a clean shutdown rather than a retryable error.

Example fix

// before — reuse after close
cc, _ := grpc.NewClient(target)
cc.Close()
client.SayHello(ctx, req) // -> connection is closing

// after — create a fresh client to reconnect
cc, _ := grpc.NewClient(target)
// ... use cc ...
cc.Close()
cc2, _ := grpc.NewClient(target)
defer cc2.Close()
Defensive patterns

Strategy: validation

Validate before calling

// Treat Close as terminal; do not reuse the ClientConn
func dialOnce(target string) *grpc.ClientConn {
    cc, err := grpc.NewClient(target, /* creds */)
    if err != nil { panic(err) }
    return cc // caller owns Close(); never use after Close()
}

Try / catch

if errors.Is(err, grpc.ErrClientConnClosing) || status.Code(err) == codes.Canceled {
    // channel is shutting down; do not retry on the same ClientConn
}

Prevention

When it happens

Trigger: ClientConn.Close() was called (or is in progress) while an RPC or connection attempt is outstanding; the dial context was cancelled before a transport was established; the channel is re-entering idle while a connection attempt races.

Common situations: Calling Close() then reusing the same *grpc.ClientConn; cancelling the DialContext; application shutdown racing with in-flight RPCs; defer-ordered teardown that closes the channel before pending calls return.

Related errors


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