{"record":{"id":"9b4430a8d250e78f","repo":"dotnet/yarp","slug":"the-ireverseproxyfeature-destinations-collection-w-9b4430","errorCode":null,"errorMessage":"The IReverseProxyFeature Destinations collection was not set.","messagePattern":"The IReverseProxyFeature Destinations collection was not set\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Forwarder/ForwarderMiddleware.cs","lineNumber":43,"sourceCode":"    {\n        ArgumentNullException.ThrowIfNull(next);\n        ArgumentNullException.ThrowIfNull(logger);\n        ArgumentNullException.ThrowIfNull(forwarder);\n        ArgumentNullException.ThrowIfNull(randomFactory);\n        _next = next;\n        _logger = logger;\n        _forwarder = forwarder;\n        _randomFactory = randomFactory;\n    }\n\n    /// <inheritdoc/>\n    public async Task Invoke(HttpContext context)\n    {\n        ArgumentNullException.ThrowIfNull(context);\n\n        var reverseProxyFeature = context.GetReverseProxyFeature();\n        var destinations = reverseProxyFeature.AvailableDestinations\n            ?? throw new InvalidOperationException($\"The {nameof(IReverseProxyFeature)} Destinations collection was not set.\");\n\n        var route = context.GetRouteModel();\n        var cluster = route.Cluster!;\n\n        var activity = context.GetYarpActivity();\n        activity?.AddTag(\"proxy.route_id\", route.Config.RouteId);\n        activity?.AddTag(\"proxy.cluster_id\", cluster.ClusterId);\n\n        if (destinations.Count == 0)\n        {\n            Log.NoAvailableDestinations(_logger, cluster.ClusterId);\n            context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;\n            context.Features.Set<IForwarderErrorFeature>(new ForwarderErrorFeature(ForwarderError.NoAvailableDestinations, ex: null));\n            activity?.SetStatus(ActivityStatusCode.Error);\n            activity?.AddError(\"Proxy forwarding failed\", \"No available destinations to forward to\");\n            return;\n        }\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Forwarder/ForwarderMiddleware.cs#L25-L61","documentation":"Thrown by ForwarderMiddleware.Invoke when IReverseProxyFeature.AvailableDestinations is null. This is the main proxy forwarding middleware; it expects an upstream pipeline stage (load balancing / destination resolution) to have populated the available destinations. A null value signals the proxy feature was not initialized for the request.","triggerScenarios":"The forwarder middleware runs before destinations are set on IReverseProxyFeature, or the feature was not attached. Usually caused by incorrect middleware ordering within MapReverseProxy.","commonSituations":"Omitting UseLoadBalancing before the forwarder. Custom middleware nulling AvailableDestinations. Pipeline built manually in the wrong order.","solutions":["Use the standard MapReverseProxy pipeline order: load balancing, then passive health checks, then the forwarder (AddForwarder is included by default).","Do not set AvailableDestinations to null in custom middleware.","Ensure the route matched has a cluster with at least one destination."],"exampleFix":"// before — manual pipeline missing load balancing\napp.MapReverseProxy(p => p.UseForwarder());\n// after\napp.MapReverseProxy(p =>\n{\n    p.UseLoadBalancing();\n    p.UseForwarder();\n});","handlingStrategy":"validation","validationCode":"var feature = context.GetReverseProxyFeature();\nif (feature.AvailableDestinations is null)\n{\n    context.Response.StatusCode = 503;\n    return;\n}","typeGuard":"static bool HasDestinations(HttpContext ctx) =>\n    ctx.GetReverseProxyFeature().AvailableDestinations is not null;","tryCatchPattern":"try { await _next(context); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Destinations collection was not set\"))\n{ context.Response.StatusCode = 503; }","preventionTips":["Use the standard MapReverseProxy pipeline with load balancing before the forwarder.","Do not clear AvailableDestinations in custom middleware.","Validate clusters/routes at startup."],"tags":["middleware","forwarder","pipeline-ordering","reverse-proxy-feature"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}