grpc/grpc-go · warning

request info not found from context

Error message

request info not found from context

What it means

dualPerRPCCreds.GetRequestMetadata requires credentials.RequestInfoFromContext(ctx) to return ok=true so it can inspect AuthInfo.AuthType() and pick ALTS vs TLS per-RPC creds (google.go:165-168). gRPC's transport layer always attaches RequestInfo before invoking GetRequestMetadata, so ok=false means the call was made outside the normal RPC path.

Source

Thrown at credentials/google/google.go:167

	if mode == internal.CredsBundleModeFallback || mode == internal.CredsBundleModeBackendFromBalancer {
		newCreds.perRPCCreds = newCreds.opts.PerRPCCreds
	}

	return newCreds, nil
}

// dualPerRPCCreds implements credentials.PerRPCCredentials by embedding the
// fallback PerRPCCredentials and the ALTS one. It pickes one of them based on
// the channel type.
type dualPerRPCCreds struct {
	perRPCCreds     credentials.PerRPCCredentials
	altsPerRPCCreds credentials.PerRPCCredentials
}

func (d *dualPerRPCCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	ri, ok := credentials.RequestInfoFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("request info not found from context")
	}
	if authType := ri.AuthInfo.AuthType(); authType == "alts" {
		return d.altsPerRPCCreds.GetRequestMetadata(ctx, uri...)
	}
	// This ensures backward compatibility even if authType is not "tls".
	return d.perRPCCreds.GetRequestMetadata(ctx, uri...)
}

func (d *dualPerRPCCreds) RequireTransportSecurity() bool {
	return d.altsPerRPCCreds.RequireTransportSecurity() || d.perRPCCreds.RequireTransportSecurity()
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Do not call GetRequestMetadata manually; let gRPC invoke it during a real RPC where RequestInfo is attached.
  2. In tests, build the context with credentials.NewContextWithRequestInfo(ctx, credentials.RequestInfo{AuthInfo: ...}) before calling.
  3. If you maintain a custom transport, set requestInfoKey via NewContextWithRequestInfo before per-RPC credential calls.

Example fix

// before (test): context has no RequestInfo
md, err := dualCreds.GetRequestMetadata(context.Background())

// after (test): attach RequestInfo like gRPC does
ctx := credentials.NewContextWithRequestInfo(context.Background(), credentials.RequestInfo{
    AuthInfo: /* your AuthInfo impl */,
})
md, err := dualCreds.GetRequestMetadata(ctx)
Defensive patterns

Strategy: validation

Validate before calling

// In tests, attach RequestInfo exactly like gRPC does.
func ctxWithRequestInfo(ctx context.Context, ai credentials.AuthInfo) context.Context {
    return credentials.NewContextWithRequestInfo(ctx, credentials.RequestInfo{AuthInfo: ai})
}
md, err := dualCreds.GetRequestMetadata(ctxWithRequestInfo(ctx, ai))

Try / catch

md, err := dualCreds.GetRequestMetadata(ctx)
if err != nil && strings.Contains(err.Error(), "request info not found from context") {
    // called outside the RPC path: attach RequestInfo or invoke via a real RPC.
    return nil, fmt.Errorf("GetRequestMetadata called without RequestInfo in context: %w", err)
}

Prevention

When it happens

Trigger: Calling dualPerRPCCreds.GetRequestMetadata directly from application or test code without using credentials.NewContextWithRequestInfo to attach RequestInfo, or a custom transport stack that did not set requestInfoKey on the context.

Common situations: Unit tests exercising per-RPC creds in isolation, a manually-constructed context for a custom transport, or a gRPC version mismatch where the key attachment contract changed.

Related errors


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