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

Thrown by getSecurityLevel in local/local.go:82 when the remote address is not recognized as a local connection (loopback 127.* or [::1]:, a Windows named pipe, or a unix-domain socket). local.NewCredentials() infers the security level purely from the connection type and refuses to run on non-local transports because it would otherwise imply a security guarantee it cannot provide.

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 03255a9237)

Solutions

  1. Use TLS (credentials.NewClientTLSFromFile / NewTLS) for any non-loopback, non-UDS destination.
  2. Ensure the dial target really is loopback (127.0.0.1 / localhost / [::1]) or a unix: scheme address when using local creds.
  3. If you must keep plaintext over the wire, use insecure credentials explicitly — but only for non-sensitive traffic.

Example fix

// before
conn, _ := grpc.NewClient("10.0.0.5:50051",
    grpc.WithTransportCredentials(local.NewCredentials()),
)

// after
conn, _ := grpc.NewClient("10.0.0.5:50051",
    grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(caPool, "10.0.0.5")),
)
Defensive patterns

Strategy: validation

Validate before calling

func isLocalTarget(addr string) bool {
    h, _, _ := net.SplitHostPort(addr)
    h = strings.ToLower(h)
    return h == "" || strings.HasPrefix(addr, "127.") || strings.HasPrefix(addr, "[::1]:") ||
        h == "localhost" || strings.HasPrefix(addr, "unix:") || strings.HasPrefix(addr, "\\\\\\\\.\\pipe\\\\")
}
if !isLocalTarget(addr) {
    creds = credentials.NewClientTLSFromCert(caPool, "") // use TLS, not local.NewCredentials()
}

Try / catch

// Connection-time error from ClientHandshake/ServerHandshake:
if strings.Contains(err.Error(), "non-local address") {
    // switch dial target to loopback/UDS or switch to TLS credentials
}

Prevention

When it happens

Trigger: Calling grpc.WithTransportCredentials(local.NewCredentials()) against a remote host (e.g. 10.0.0.5:50051 or a DNS name resolving off-box), or a unix socket path that dialer resolved to a TCP address. Fires on both ClientHandshake (line 87) and ServerHandshake (line 95).

Common situations: Promoting a local-only prototype to a real network address without swapping local creds for TLS; a test that uses local creds but dials an in-process listener bound to 0.0.0.0; misconfigured UDS address that the resolver maps to TCP.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/fb1d62310aad0b00. Report an issue: GitHub.