{"record":{"id":"97225e157f834de3","repo":"grpc/grpc-go","slug":"grpc-the-connection-is-closing","errorCode":null,"errorMessage":"grpc: the connection is closing","messagePattern":"grpc: the connection is closing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientconn.go","lineNumber":74,"sourceCode":"\t_ \"google.golang.org/grpc/resolver/dns\"                  // To register dns resolver.\n)\n\nconst (\n\t// minimum time to give a connection to complete\n\tminConnectTimeout = 20 * time.Second\n)\n\nvar (\n\t// ErrClientConnClosing indicates that the operation is illegal because\n\t// the ClientConn is closing.\n\t//\n\t// Deprecated: this error should not be relied upon by users; use the status\n\t// code of Canceled instead.\n\tErrClientConnClosing = status.Error(codes.Canceled, \"grpc: the client connection is closing\")\n\t// errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs.\n\terrConnDrain = errors.New(\"grpc: the connection is drained\")\n\t// errConnClosing indicates that the connection is closing.\n\terrConnClosing = errors.New(\"grpc: the connection is closing\")\n\t// errConnIdling indicates the connection is being closed as the channel\n\t// is moving to an idle mode due to inactivity.\n\terrConnIdling = errors.New(\"grpc: the connection is closing due to channel idleness\")\n\t// invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default\n\t// service config.\n\tinvalidDefaultServiceConfigErrPrefix = \"grpc: the provided default service config is invalid\"\n\t// PickFirstBalancerName is the name of the pick_first balancer.\n\tPickFirstBalancerName = pickfirst.Name\n)\n\n// The following errors are returned from Dial and DialContext\nvar (\n\t// errNoTransportSecurity indicates that there is no transport security\n\t// being set for ClientConn. Users should either set one or explicitly\n\t// call WithInsecure DialOption to disable security.\n\terrNoTransportSecurity = errors.New(\"grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)\")\n\t// errTransportCredsAndBundle indicates that creds bundle is used together\n\t// with other individual Transport Credentials.","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/clientconn.go#L56-L92","documentation":"Raised by grpc-go's client connection machinery (clientconn.go) as errConnClosing = errors.New(\"grpc: the connection is closing\"). It means the HTTP/2 transport underlying a ClientConn is being torn down, so an RPC attempt (or other per-connection operation) is rejected because the connection is closing and cannot accept or continue work. Note the related, deprecated ErrClientConnClosing (status code Canceled, \"grpc: the client connection is closing\"): grpc-go's own guidance is to stop matching on these sentinel errors and instead check for status code Canceled via status.FromError.","triggerScenarios":"Calling an RPC on a ClientConn while the connection is being closed — most commonly invoking an RPC after (or concurrently with) conn.Close(). Also hit when a SubConn's transport is closing/draining (see the sibling errConnDrain) or being closed for channel idleness (errConnIdling), so a picker hands out an RPC right as the transport goes away. Distinguish it from the deprecated exported ErrClientConnClosing (codes.Canceled, 'grpc: the client connection is closing') which is returned when the ClientConn itself is closing.","commonSituations":"Application code that closes the ClientConn (defer conn.Close()) while outstanding or in-flight RPCs are still running; shared-connection code where one goroutine tears down the connection while another dials or invokes RPCs; test harnesses that Close() the conn in t.Cleanup before a background RPC finishes; server-side connection teardown racing a client's streaming call. If you see the variant 'grpc: the connection is closing due to channel idleness', the channel entered idle mode (see grpc.WithIdleTimeout).","solutions":["Check for races between conn.Close() and RPC use: ensure Close() is only called after all RPCs on that ClientConn have finished (e.g., wait on the RPC calls/streams or a WaitGroup before closing).","If the connection is already closed, do not reuse the ClientConn — create a new one (grpc.NewClient / grpc.DialContext) for further calls.","Do not string-match or errors.Is against the internal errConnClosing (it is unexported). If you need to detect connection shutdown programmatically, check the status code: errCode, ok := status.FromError(err); use errCode.Code() == codes.Canceled, per the deprecation note on ErrClientConnClosing.","For the idleness variant, either keep the channel active, disable/extend idleness via grpc.WithIdleTimeout, or handle reconnects by retrying on a fresh connection."],"exampleFix":"// before:\ntypedConfig := &anypb.Any{\n    TypeUrl: \"\",  // or \"grpc.authz.audit_logging/\"\n    Value:   rawJSON,\n}\n\n// after:\ntypedConfig := &anypb.Any{\n    TypeUrl: \"grpc.authz.audit_logging/stdout\",\n    Value:   rawJSON,\n}","handlingStrategy":"validation","validationCode":"// Validate the TypeURL resolves to a non-empty logger name:\nfunc validateTypeURL(typeURL string) error {\n    parts := strings.Split(typeURL, \"/\")\n    name := parts[len(parts)-1]\n    if name == \"\" {\n        return fmt.Errorf(\"type_url %q resolves to empty logger name\", typeURL)\n    }\n    if audit.GetLoggerBuilder(name) == nil {\n        return fmt.Errorf(\"no logger builder registered for %q\", name)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set type_url to a URL-formatted string with the logger name after the last '/' (e.g., grpc.authz.audit_logging/stdout).","Cross-reference the type_url name against audit.GetLoggerBuilder before sending the config.","Use consistent naming conventions for custom audit logger registrations."],"tags":["xds","rbac","grpc","audit","config","type-url"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}