{"record":{"id":"8c371426941121ce","repo":"grpc/grpc-go","slug":"request-info-not-found-from-context","errorCode":null,"errorMessage":"request info not found from context","messagePattern":"request info not found from context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/google/google.go","lineNumber":167,"sourceCode":"\tif mode == internal.CredsBundleModeFallback || mode == internal.CredsBundleModeBackendFromBalancer {\n\t\tnewCreds.perRPCCreds = newCreds.opts.PerRPCCreds\n\t}\n\n\treturn newCreds, nil\n}\n\n// dualPerRPCCreds implements credentials.PerRPCCredentials by embedding the\n// fallback PerRPCCredentials and the ALTS one. It pickes one of them based on\n// the channel type.\ntype dualPerRPCCreds struct {\n\tperRPCCreds     credentials.PerRPCCredentials\n\taltsPerRPCCreds credentials.PerRPCCredentials\n}\n\nfunc (d *dualPerRPCCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {\n\tri, ok := credentials.RequestInfoFromContext(ctx)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"request info not found from context\")\n\t}\n\tif authType := ri.AuthInfo.AuthType(); authType == \"alts\" {\n\t\treturn d.altsPerRPCCreds.GetRequestMetadata(ctx, uri...)\n\t}\n\t// This ensures backward compatibility even if authType is not \"tls\".\n\treturn d.perRPCCreds.GetRequestMetadata(ctx, uri...)\n}\n\nfunc (d *dualPerRPCCreds) RequireTransportSecurity() bool {\n\treturn d.altsPerRPCCreds.RequireTransportSecurity() || d.perRPCCreds.RequireTransportSecurity()\n}\n","sourceCodeStart":149,"sourceCodeEnd":179,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/credentials/google/google.go#L149-L179","documentation":"Returned by dualPerRPCCreds.GetRequestMetadata when credentials.RequestInfoFromContext returns ok=false, meaning the RPC context carries no transport/peer auth info. dualPerRPCCreds needs the AuthType to decide between ALTS and TLS per-RPC credentials, so without request info it cannot route correctly. This typically indicates the credential was used outside a normal gRPC RPC pipeline.","triggerScenarios":"Invoking dualPerRPCCreds.GetRequestMetadata directly (not via gRPC) with a plain context; a custom dialOption or interceptor that strips request info from the context before per-RPC credentials run; an older gRPC version that did not populate request info on the context.","commonSituations":"Unit tests that call GetRequestMetadata with context.Background(); middleware that re-creates the context losing the gRPC-added values; version skew between grpc core and the credentials/google subpackage.","solutions":["Do not call dualPerRPCCreds.GetRequestMetadata directly; let gRPC invoke it during a real RPC.","If testing, attach request info via credentials.NewContextWithRequestInfo or use the grpc test suite helpers.","Upgrade google.golang.org/grpc so the transport reliably attaches request info to the context."],"exampleFix":"// before\nmd, err := dualCreds.GetRequestMetadata(context.Background())\n// after\n// Let gRPC call GetRequestMetadata during a real RPC over a dialed connection.","handlingStrategy":"validation","validationCode":"// dualPerRPCCreds is internal; do not call its GetRequestMetadata directly.\n// If you must (tests), attach request info first:\nfunc ctxWithRequestInfo(authInfo credentials.AuthInfo) context.Context {\n    return credentials.NewContextWithRequestInfo(context.Background(), authInfo)\n}","typeGuard":null,"tryCatchPattern":"// This error indicates misuse; fix the caller rather than catching at runtime:\nmd, err := creds.GetRequestMetadata(ctx)\nif err != nil && strings.Contains(err.Error(), \"request info not found\") {\n    panic(\"GetRequestMetadata called outside gRPC RPC pipeline\")\n}","preventionTips":["Never invoke dualPerRPCCreds.GetRequestMetadata outside a real RPC.","In tests, use the gRPC testbufconn framework so request info is populated.","Avoid interceptors that replace the context without preserving gRPC values."],"tags":["grpc","context","credentials","alts","internal"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}