# 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-failed`
- **Domain:** go
- **Category:** auth_error
- **Verification:** ai_generated
- **Fix Rate:** 80%

## Root Cause

The gRPC client connected with TLS but the server's certificate chain is not trusted by the client's root CA pool.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| google.golang.org/grpc 1.0+ | active | — | — |

## Workarounds

1. **** (95% success)
   ```
   Load the correct CA into the client's root pool:
certPool := x509.NewCertPool()
pem, _ := os.ReadFile("ca.pem")
certPool.AppendCertsFromPEM(pem)
creds := credentials.NewTLS(&tls.Config{RootCAs: certPool})
conn, _ := grpc.NewClient(addr, grpc.WithTransportCredentials(creds))
   ```
2. **** (90% success)
   ```
   For internal/self-signed setups, use mTLS with a shared CA:
creds := credentials.NewTLS(&tls.Config{
    Certificates: []tls.Certificate{clientCert},
    RootCAs:      certPool,
    ServerName:   "api.internal",
})
   ```

## Dead Ends

- **** — Disables all certificate validation, exposing the client to MITM; not acceptable in production. (60% fail)
- **** — Certificate trust is deterministic; retries fail identically. (95% fail)
