{"record":{"id":"898919f7c6978b01","repo":"dotnet/yarp","slug":"the-typeof-ireverseproxyfeature-fullname-is-mis","errorCode":null,"errorMessage":"The {typeof(IReverseProxyFeature).FullName} is missing the {typeof(RouteModel).FullName}.","messagePattern":"The (.+?) is missing the (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Model/HttpContextFeaturesExtensions.cs","lineNumber":23,"sourceCode":"using Yarp.ReverseProxy.Model;\nusing Yarp.ReverseProxy.Forwarder;\n\nnamespace Microsoft.AspNetCore.Http;\n\n/// <summary>\n/// Extension methods for fetching proxy configuration from the current HttpContext.\n/// </summary>\npublic static class HttpContextFeaturesExtensions\n{\n    /// <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>();","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Model/HttpContextFeaturesExtensions.cs#L5-L41","documentation":"`GetRouteModel()` retrieves the `IReverseProxyFeature` from the `HttpContext` and then accesses its `Route` property. If the feature exists but `Route` is null, this means the proxy pipeline initialized the feature without associating a `RouteModel` — an internal inconsistency. This extension method is meant to be called during request processing within the proxy pipeline where routes are always populated.","triggerScenarios":"`GetRouteModel()` is called in code that runs outside the YARP proxy pipeline (before `ProxyPipelineInitializerMiddleware` sets the feature), or the `IReverseProxyFeature` was manually created/overwritten with a `ReverseProxyFeature` instance whose `Route` property was left null. The check at line 22 finds `proxyFeature.Route == null` and throws.","commonSituations":"A developer calls `context.GetRouteModel()` in middleware that runs before the proxy pipeline has initialized the feature. Someone manually constructs a `ReverseProxyFeature` (e.g., in `ReassignProxyRequest`) and forgets to copy the `Route` property. Custom middleware replaces the feature with an incomplete instance.","solutions":["Ensure `GetRouteModel()` is only called within or after the YARP proxy pipeline (after `ProxyPipelineInitializerMiddleware` has run).","If manually creating a `ReverseProxyFeature` (e.g., via `ReassignProxyRequest`), always copy the `Route` from the old feature.","Use `context.GetReverseProxyFeature().Route` with a null check rather than `GetRouteModel()` if the route may legitimately be absent.","Verify that the endpoint reaching your middleware was actually mapped through YARP's `MapReverseProxy()`."],"exampleFix":"// before — manual feature creation without Route\nvar newFeature = new ReverseProxyFeature\n{\n    Cluster = newCluster.Model,\n    AllDestinations = newCluster.DestinationsState.AllDestinations,\n    AvailableDestinations = newCluster.DestinationsState.AvailableDestinations,\n    Route = null // bug!\n};\ncontext.Features.Set(newFeature);\n// after — always carry Route from the old feature\nvar oldFeature = context.GetReverseProxyFeature();\nvar newFeature = new ReverseProxyFeature\n{\n    Cluster = newCluster.Model,\n    AllDestinations = newCluster.DestinationsState.AllDestinations,\n    AvailableDestinations = newCluster.DestinationsState.AvailableDestinations,\n    Route = oldFeature.Route // preserve route reference\n};\ncontext.Features.Set(newFeature);","handlingStrategy":"validation","validationCode":"// Safe access pattern for route model\nvar feature = context.Features.Get<IReverseProxyFeature>();\nif (feature?.Route is null)\n{\n    // Not in a proxied context, or feature not fully initialized\n    context.Response.StatusCode = 500;\n    return;\n}\nvar route = feature.Route;","typeGuard":"static RouteModel? TryGetRouteModel(HttpContext context)\n{\n    return context.Features.Get<IReverseProxyFeature>()?.Route;\n}","tryCatchPattern":"// Not recommended to catch — use a null-safe access pattern instead.\n// If you must: only call GetRouteModel() from within the proxy pipeline.","preventionTips":["Only call GetRouteModel() from code inside the YARP proxy pipeline.","Use `context.Features.Get<IReverseProxyFeature>()?.Route` with a null check for defensive access.","When constructing a new ReverseProxyFeature manually, always copy Route from the old feature."],"tags":["feature","pipeline","route-model","api-misuse","middleware"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}