# rpc error: code = Unavailable desc = connection error: desc = "transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate signed by unknown authority"

- **ID:** `go/grpc-tls-handshake-failure`
- **Domain:** go
- **Category:** auth_error
- **Verification:** ai_generated
- **Fix Rate:** 80%

## Root Cause

The client's root CA pool does not contain the CA that signed the server certificate. Common with self-signed certs, internal CAs, or missing grpc.WithTransportCredentials.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| 1.50+ | active | — | — |

## Workarounds

1. **** (93% success)
   ```
   b, _ := os.ReadFile("ca.pem")
cp := x509.NewCertPool()
cp.AppendCertsFromPEM(b)
creds := credentials.NewTLS(&tls.Config{RootCAs: cp, ServerName: "myservice.internal"})
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(creds))
   ```
2. **** (85% success)
   ```
   creds := credentials.NewTLS(&tls.Config{})
// or explicitly:
// tls.Config{RootCAs: nil} uses the host's system pool
   ```

## Dead Ends

- **** — Disables certificate validation entirely, exposing the connection to MITM. Not acceptable in production. (90% fail)
- **** — Mismatches the server's TLS listener; the handshake fails with a different error (record layer failure). (85% fail)
