go auth_error ai_generated true

rpc error: code = PermissionDenied desc = transport: authentication handshake failed: tls: first record does not look like a TLS handshake

ID: go/grpc-permission-denied-tls

Also available as: JSON · Markdown · 中文
80%Fix Rate
88%Confidence
0Evidence
2024-04-11First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
1.50+ active — — —

Root Cause

Client used TLS credentials but the server is serving plaintext (or vice versa). The server received a TLS ClientHello but expected HTTP/2 plaintext.

generic

中文

客户端使用了 TLS 凭据但服务端以明文提供服务(或反之)。服务端收到 TLS ClientHello 却期望 HTTP/2 明文。

Workarounds

  1. 92% success
    Match client/server transport mode. For plaintext servers:
    conn, _ := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    For TLS servers:
    creds := credentials.NewTLS(&tls.Config{RootCAs: pool})
    conn, _ := grpc.NewClient(addr, grpc.WithTransportCredentials(creds))
  2. 80% success
    Inspect the server's actual protocol with openssl/curl before dialing:
    openssl s_client -connect host:port -alpn h2 < /dev/null

Dead Ends

Common approaches that don't work:

  1. 90% fail

    The error is not about cert validation — the bytes aren't TLS at all; skipping verification doesn't change the wire format.

  2. 85% fail

    Root CAs only matter after the handshake begins; here the handshake never starts.