Search code examples
gosslconnectiongrpc

How do I get last connection error when dialling gRPC server?


I am having the following code:

dialCtx, cancel := context.WithTimeout(ctx, 120*time.Second)
defer cancel()

conn, err := grpc.DialContext(dialCtx, address,
    grpc.WithTransportCredentials(creds),
    grpc.WithKeepaliveParams(keepAlive),
    grpc.WithBlock(),
)
if err != nil {
    return fmt.Errorf("failed to connect to server: %v", err)
}

I am trying to create a connection with gRPC server. One important thing is that I am using WithBlock() which blocks the dial until the connection is ready or the context timeouts. Okay, but when the context timeouts, I don't get what was the connection problem, aka last connection error. I get context deadline exceeded.

I tried following:

  • Using grpc.FailOnNonTempDialError(true) - error is returned when service is not available, but when TLS verification fails, re-connection continues.
  • Using grpc.WithContextDialer(...) - does not work for me, because sometimes the initial dialling is successful, but if server certificates validation fails, whole connection is closed.

How can I get that last connection error?


Solution

  • After some more research, I decided to update the grpc package version. I was using v1.27.0 and the latest is v1.35.0. Between these version, the problem was fixed and a new dial option introduced:

    grpc.WithReturnConnectionError()
    

    It's a way better now, but there is room for improvement. Currently, lastError and the context error are combined like that:

    conn, err = nil, fmt.Errorf("%v: %v", ctx.Err(), err)
    

    The problem is that the underlying error's type is lost, so the only way to make some action, based on the error, is string comparing(which is not reliable).

    I hope that answer will be useful.