grpc/grpc-go · error
local credentials rejected connection to non-local address
Error message
local credentials rejected connection to non-local address %q
What it means
Returned by getSecurityLevel (during ClientHandshake/ServerHandshake) when the peer address is not recognized as a local connection: it is not 127.x, not [::1], not a Windows named pipe, and not a unix socket. The local credentials package is intentionally unsafe for remote peers, so it refuses the handshake.
Solutions
- Only use local.NewCredentials() for loopback (127.0.0.1 / ::1) or unix-socket connections.
- For non-local peers, switch to credentials.NewTLS or alts.NewClientCreds.
- Connect via unix://<socket-path> or 127.0.0.1:<port> when using local credentials.
Example fix
// before
conn, _ := grpc.Dial("10.0.0.5:50051", grpc.WithTransportCredentials(local.NewCredentials()))
// after
conn, _ := grpc.Dial("127.0.0.1:50051", grpc.WithTransportCredentials(local.NewCredentials()))
// or
conn, _ := grpc.Dial("unix:///tmp/my.sock", grpc.WithTransportCredentials(local.NewCredentials())) Defensive patterns
Strategy: validation
Validate before calling
func isLocalAddr(addr string) bool {
return strings.HasPrefix(addr, "127.") ||
strings.HasPrefix(addr, "[::1]") ||
strings.HasPrefix(addr, "unix:")
}
if !isLocalAddr(peerAddr) {
log.Fatalf("local credentials only valid for loopback/UDS, got %q", peerAddr)
} Type guard
func safeForLocalCreds(network, addr string) bool {
switch {
case strings.HasPrefix(addr, "127."), strings.HasPrefix(addr, "[::1]:"):
return true
case network == "pipe" && strings.HasPrefix(addr, `\\.\pipe\`):
return true
case network == "unix":
return true
}
return false
} Prevention
- Use local.NewCredentials() only for 127.0.0.1, ::1, or unix sockets.
- Switch to TLS or ALTS for any non-loopback peer.
- Resolve hostnames before dialing to ensure they map to loopback.
When it happens
Trigger: Using local.NewCredentials() on a connection to a non-loopback IP (e.g. 10.0.0.5, a public address) or a TCP connection to the machine's external IP; connecting via a hostname that resolves to a non-loopback address.
Common situations: Local-dev convenience credential accidentally used in a multi-node cluster; service binding to 0.0.0.0 and connecting via the pod IP; switching from UDS to TCP without changing the credential.
Related errors
- AuthInfo is nil
- cannot send secure credentials on an insecure connection
- credentials: cannot send secure credentials on an insecure…
- credentials: rawConn is dispatched out of gRPC
- delegating_resolver: failed to determine proxy URL for…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/fb1d62310aad0b00.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/local/local.go:82
return c.info
}
// getSecurityLevel returns the security level for a local connection.
// It returns an error if a connection is not local.
func getSecurityLevel(network, addr string) (credentials.SecurityLevel, error) {
switch {
// Local TCP connection
case strings.HasPrefix(addr, "127."), strings.HasPrefix(addr, "[::1]:"):
return credentials.NoSecurity, nil
// Windows named pipe connection
case network == "pipe" && strings.HasPrefix(addr, `\\.\pipe\`):
return credentials.NoSecurity, nil
// UDS connection
case network == "unix":
return credentials.PrivacyAndIntegrity, nil
// Not a local connection and should fail
default:
return credentials.InvalidSecurityLevel, fmt.Errorf("local credentials rejected connection to non-local address %q", addr)
}
}
func (*localTC) ClientHandshake(_ context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
secLevel, err := getSecurityLevel(conn.RemoteAddr().Network(), conn.RemoteAddr().String())
if err != nil {
return nil, nil, err
}
return conn, info{credentials.CommonAuthInfo{SecurityLevel: secLevel}}, nil
}
func (*localTC) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
secLevel, err := getSecurityLevel(conn.RemoteAddr().Network(), conn.RemoteAddr().String())
if err != nil {
return nil, nil, err
}
return conn, info{credentials.CommonAuthInfo{SecurityLevel: secLevel}}, nil
}View on GitHub (pinned to 0c51461d27)