grpc/grpc-go · error
grpc: the credentials require transport level security (use
Error message
grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)
What it means
errTransportCredentialsMissing (clientconn.go:97-100) is returned by validateTransportCredentials (clientconn.go:494-499) when transport security is 'insecure' AND a PerRPCCredentials whose RequireTransportSecurity()==true is configured. You cannot send security-sensitive call credentials (e.g. OAuth/JWT) over a plaintext channel.
Source
Thrown at clientconn.go:100
PickFirstBalancerName = pickfirst.Name
)
// The following errors are returned from Dial and DialContext
var (
// errNoTransportSecurity indicates that there is no transport security
// being set for ClientConn. Users should either set one or explicitly
// call WithInsecure DialOption to disable security.
errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly or set credentials)")
// errTransportCredsAndBundle indicates that creds bundle is used together
// with other individual Transport Credentials.
errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle may not be used with individual TransportCredentials")
// errNoTransportCredsInBundle indicated that the configured creds bundle
// returned a transport credentials which was nil.
errNoTransportCredsInBundle = errors.New("grpc: credentials.Bundle must return non-nil transport credentials")
// errTransportCredentialsMissing indicates that users want to transmit
// security information (e.g., OAuth2 token) which requires secure
// connection on an insecure connection.
errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
)
var (
disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
Name: "grpc.subchannel.disconnections",
Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.",
Unit: "{disconnection}",
Labels: []string{"grpc.target"},
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality", "grpc.disconnect_error"},
Default: false,
})
connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{
Name: "grpc.subchannel.connection_attempts_succeeded",
Description: "EXPERIMENTAL. Number of successful connection attempts.",
Unit: "{attempt}",
Labels: []string{"grpc.target"},
OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality"},
Default: false,View on GitHub (pinned to 03255a9237)
Solutions
- Use TLS transport (WithTransportCredentials(credentials.NewTLS(...))) so the per-RPC credentials are protected.
- If you genuinely want plaintext, remove the RequireTransportSecurity per-RPC credentials or supply per-RPC creds whose RequireTransportSecurity() returns false.
- For dev only, wrap your token logic in a credential type that returns false from RequireTransportSecurity() — never do this in production.
- Audit WithPerRPCCredentials entries; the check fires on the first one requiring transport security.
Example fix
// before — insecure transport + OAuth creds
cc, _ := grpc.NewClient(target,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithPerRPCCredentials(oauth.TokenSource{oauth2.TokenSource: ts}))
// err: grpc: the credentials require transport level security ...
// after — TLS so per-RPC creds are protected
cc, _ := grpc.NewClient(target,
grpc.WithTransportCredentials(credentials.NewTLS(tlsConf)),
grpc.WithPerRPCCredentials(oauth.TokenSource{oauth2.TokenSource: ts})) Defensive patterns
Strategy: validation
Validate before calling
// Reject per-RPC creds that require TLS when transport is insecure
func safePerRPC(c credentials.PerRPCCredentials, insecure bool) error {
if insecure && c.RequireTransportSecurity() {
return errors.New("per-RPC creds require TLS; refusing insecure transport")
}
return nil
} Type guard
func requiresTLS(c credentials.PerRPCCredentials) bool {
return c != nil && c.RequireTransportSecurity()
} Try / catch
cc, err := grpc.NewClient(target, opts...)
if err != nil && strings.Contains(err.Error(), "require transport level security") {
// swap insecure for TLS, or drop the requiring per-RPC creds
} Prevention
- Use TLS whenever attaching OAuth/JWT per-RPC credentials.
- For local dev, use per-RPC creds with RequireTransportSecurity()==false instead of stripping TLS.
- Audit WithPerRPCCredentials entries before going insecure.
When it happens
Trigger: NewClient is called with insecure.NewCredentials() (or any creds whose Info().SecurityProtocol=="insecure") together with WithPerRPCCredentials(creds) where creds.RequireTransportSecurity() returns true. Detected at clientconn.go:494-497.
Common situations: Local dev with insecure transport but production-style OAuth token attach; mixing insecure creds with oauth.TokenSource / JWT credentials that flag RequireTransportSecurity; partial migration where TLS was removed but per-RPC creds were not.
Related errors
- grpc: no transport security set (use grpc.WithTransportCrede
- grpc: credentials.Bundle may not be used with individual Tra
- grpc: credentials.Bundle must return non-nil transport crede
- AuthInfo is nil
- ALTS: untrusted platform. ALTS is only supported on GCP
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/bb7562fb09cdb1d7.
Report an issue: GitHub.