gRPC "transport: authentication handshake failed" (TLS) in CI
gRPC reports "transport: authentication handshake failed" when the TLS handshake to the server does not complete. The runner could not validate the server certificate, the SNI/hostname did not match, or the client used plaintext against a TLS server.
What this error means
A call fails with "rpc error: code = Unavailable desc = connection error: desc = \"transport: authentication handshake failed: x509: certificate signed by unknown authority\"" or a hostname mismatch in CI.
rpc error: code = Unavailable desc = connection error: desc =
"transport: authentication handshake failed: x509: certificate signed by unknown authority"Common causes
The runner does not trust the server certificate
A self-signed or internal-CA certificate is not in the runner's trust store, so the handshake fails with "signed by unknown authority".
A plaintext/TLS or hostname mismatch
The client dials plaintext against a TLS server (or the cert's SAN does not match the dialed host), aborting the handshake.
How to fix it
Provide the CA and match the hostname
- Pass the CA that signed the server certificate to the client credentials.
- Dial a hostname that the certificate's SAN covers.
- Use TLS credentials (not insecure) when the server requires TLS.
creds := credentials.NewClientTLSFromFile("ca.pem", "api.internal")
conn, err := grpc.NewClient("api.internal:443", grpc.WithTransportCredentials(creds))Verify the handshake with grpcurl
Confirm the cert chain and hostname work outside your client code.
grpcurl -cacert ca.pem api.internal:443 listHow to prevent it
- Install the signing CA into the runner trust store or pass it explicitly.
- Dial hostnames covered by the certificate SAN.
- Match client transport (TLS vs plaintext) to the server.