{"record":{"id":"1e9f08daac32d3ce","repo":"dotnet/yarp","slug":"typeof-ireverseproxyfeature-fullname-is-missing","errorCode":null,"errorMessage":"{typeof(IReverseProxyFeature).FullName} is missing.","messagePattern":"(.+?) is missing\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Model/HttpContextFeaturesExtensions.cs","lineNumber":33,"sourceCode":"    /// <summary>\n    /// Retrieves the <see cref=\"RouteModel\"/> instance associated with the current request.\n    /// </summary>\n    public static RouteModel GetRouteModel(this HttpContext context)\n    {\n        var proxyFeature = context.GetReverseProxyFeature();\n\n        var route = proxyFeature.Route\n            ?? throw new InvalidOperationException($\"The {typeof(IReverseProxyFeature).FullName} is missing the {typeof(RouteModel).FullName}.\");\n\n        return route;\n    }\n\n    /// <summary>\n    /// Retrieves the <see cref=\"IReverseProxyFeature\"/> instance associated with the current request.\n    /// </summary>\n    public static IReverseProxyFeature GetReverseProxyFeature(this HttpContext context)\n    {\n        return context.Features.Get<IReverseProxyFeature>() ?? throw new InvalidOperationException($\"{typeof(IReverseProxyFeature).FullName} is missing.\");\n    }\n\n    /// <summary>\n    /// Retrieves the <see cref=\"IForwarderErrorFeature\"/> instance associated with the current request, if any.\n    /// </summary>\n    public static IForwarderErrorFeature? GetForwarderErrorFeature(this HttpContext context)\n    {\n        return context.Features.Get<IForwarderErrorFeature>();\n    }\n\n    // Compare to ProxyPipelineInitializerMiddleware\n    /// <summary>\n    /// Replaces the assigned cluster and destinations in <see cref=\"IReverseProxyFeature\"/> with the new <see cref=\"ClusterState\"/>,\n    /// causing the request to be sent to the new cluster instead.\n    /// </summary>\n    public static void ReassignProxyRequest(this HttpContext context, ClusterState cluster)\n    {\n        var oldFeature = context.GetReverseProxyFeature();","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Model/HttpContextFeaturesExtensions.cs#L15-L51","documentation":"`GetReverseProxyFeature()` retrieves the `IReverseProxyFeature` from `HttpContext.Features`. If the feature is not set, the request is not being processed through the YARP proxy pipeline (or the middleware hasn't run yet). This extension method is intended for use inside transforms, direct forwarding handlers, or middleware that runs within the proxy pipeline where the feature is always populated.","triggerScenarios":"`GetReverseProxyFeature()` is called in middleware or a controller that runs outside the YARP proxy pipeline — before `ProxyPipelineInitializerMiddleware.Invoke` has set the feature at line 56. The `context.Features.Get<IReverseProxyFeature>()` returns null and the throw fires.","commonSituations":"A developer calls `context.GetReverseProxyFeature()` in a regular MVC controller or Razor Page handler that is not part of a proxied route. Someone calls it in middleware registered before `MapReverseProxy()`. A direct-forwarding scenario (`MapForwarder`) calls it before the pipeline runs.","solutions":["Only call `GetReverseProxyFeature()` from code that executes within the YARP proxy pipeline — inside transforms, inside `MapReverseProxy` pipeline branches, or in middleware registered via `app.MapReverseProxy(pipeline => pipeline.Use(...))`.","If you need proxy feature data outside the pipeline, pass it through a different mechanism (e.g., items bag set earlier in the pipeline).","Guard with a null check: `context.Features.Get<IReverseProxyFeature>()` and handle the null case gracefully if the code may run outside the pipeline.","Verify the route is actually mapped through `MapReverseProxy()` or `MapForwarder()`, not through standard MVC routing."],"exampleFix":"// before — called outside the proxy pipeline, throws\napp.Use(async (context, next) =>\n{\n    var feature = context.GetReverseProxyFeature(); // throws if not in proxy pipeline\n    await next();\n});\napp.UseRouting();\napp.MapReverseProxy();\n// after — guard or move inside the pipeline\napp.MapReverseProxy(pipeline =>\n{\n    pipeline.Use(async (context, next) =>\n    {\n        var feature = context.GetReverseProxyFeature(); // safe: inside pipeline\n        await next();\n    });\n    pipeline.RunProxy();\n});","handlingStrategy":"validation","validationCode":"// Safe access pattern\nvar feature = context.Features.Get<IReverseProxyFeature>();\nif (feature is null)\n{\n    // Request is not being handled by the proxy pipeline\n    context.Response.StatusCode = 500;\n    return;\n}","typeGuard":"static IReverseProxyFeature? TryGetProxyFeature(HttpContext context)\n    => context.Features.Get<IReverseProxyFeature>();","tryCatchPattern":"// Not recommended to catch — use Features.Get<IReverseProxyFeature>() with null check instead.","preventionTips":["Only call GetReverseProxyFeature() from inside the proxy pipeline (MapReverseProxy branch or transforms).","Use `context.Features.Get<IReverseProxyFeature>()` with a null check for defensive access outside the pipeline.","Verify that the code runs after ProxyPipelineInitializerMiddleware if it needs the feature."],"tags":["feature","pipeline","api-misuse","middleware"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}