grpc/grpc-go · error
AuthInfo is nil
Error message
AuthInfo is nil
What it means
Returned by credentials.CheckSecurityLevel when the AuthInfo argument is nil. This function is typically called by PerRPCCredentials implementations (e.g., STS, oauth) via credentials.RequestInfoFromContext to verify the connection meets a minimum security level before attaching per-RPC credentials. A nil AuthInfo means the request context has no security information, usually because the RPC was made over an insecure channel or the credentials were invoked outside a real RPC.
Solutions
- Ensure the channel uses TLS or another transport security mechanism so that AuthInfo is populated.
- In unit tests, build the context with credentials.NewContextWithRequestInfo(ctx, credentials.RequestInfo{AuthInfo: ...}) to simulate a secured connection.
- If the service genuinely allows insecure connections, skip CheckSecurityLevel or handle the nil-AuthInfo case explicitly before calling it.
Example fix
// before
creds := &oauth.TokenSource{TokenSource: ts}
conn, _ := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithPerRPCCredentials(creds)) // AuthInfo is nil
// after
conn, _ := grpc.Dial(addr, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), grpc.WithPerRPCCredentials(creds)) Defensive patterns
Strategy: validation
Validate before calling
// Before CheckSecurityLevel, verify AuthInfo is populated:
ri, ok := credentials.RequestInfoFromContext(ctx)
if !ok || ri.AuthInfo == nil {
return status.Error(codes.Unauthenticated, "no security info; use a secure channel")
}
if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
return err
} Type guard
func hasAuthInfo(ctx context.Context) bool {
ri, ok := credentials.RequestInfoFromContext(ctx)
return ok && ri.AuthInfo != nil
} Try / catch
if err := credentials.CheckSecurityLevel(ri.AuthInfo, level); err != nil {
if ri.AuthInfo == nil {
// channel lacks transport security; upgrade to TLS
}
return err
} Prevention
- Always use grpc.WithTransportCredentials(TLS) on channels that carry per-RPC credentials.
- In tests, use credentials.NewContextWithRequestInfo with a populated AuthInfo.
- Guard CheckSecurityLevel with a nil check on AuthInfo first.
When it happens
Trigger: A PerRPCCredentials.GetRequestMetadata implementation calls credentials.CheckSecurityLevel(ri.AuthInfo, ...) where ri.AuthInfo is nil. This happens when the channel uses insecure.NewCredentials (no transport security), when RequestInfo was not populated (custom invocation outside gRPC), or in unit tests that call GetRequestMetadata with a bare context.
Common situations: Developers attach per-RPC credentials (like OAuth tokens) to an insecure channel, or test GetRequestMetadata without using credentials.NewContextWithRequestInfo. Also occurs when a custom call-credential implementation is invoked on a stream that bypassed the normal transport handshake.
Related errors
- cannot send secure credentials on an insecure connection
- ClientHandshake() is not supported for server credentials
- credentials: cannot send secure credentials on an insecure…
- credentials: rawConn is dispatched out of gRPC
- empty token_exchange_service_uri in options
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/4c1102b3d11fa244.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/credentials.go:295
// in ctx.
//
// This API is experimental.
func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo {
chi, _ := icredentials.ClientHandshakeInfoFromContext(ctx).(ClientHandshakeInfo)
return chi
}
// CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one.
// It returns success if 1) the condition is satisfied or 2) AuthInfo struct does not implement GetCommonAuthInfo() method
// or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility.
//
// This API is experimental.
func CheckSecurityLevel(ai AuthInfo, level SecurityLevel) error {
type internalInfo interface {
GetCommonAuthInfo() CommonAuthInfo
}
if ai == nil {
return errors.New("AuthInfo is nil")
}
if ci, ok := ai.(internalInfo); ok {
// CommonAuthInfo.SecurityLevel has an invalid value.
if ci.GetCommonAuthInfo().SecurityLevel == InvalidSecurityLevel {
return nil
}
if ci.GetCommonAuthInfo().SecurityLevel < level {
return fmt.Errorf("requires SecurityLevel %v; connection has %v", level, ci.GetCommonAuthInfo().SecurityLevel)
}
}
// The condition is satisfied or AuthInfo struct does not implement GetCommonAuthInfo() method.
return nil
}
// ChannelzSecurityInfo defines the interface that security protocols should implement
// in order to provide security info to channelz.
//
// This API is experimental.View on GitHub (pinned to 0c51461d27)