{"record":{"id":"14cdb71c27faa081","repo":"dotnet/yarp","slug":"the-ireverseproxyfeature-cluster-was-not-set","errorCode":null,"errorMessage":"The IReverseProxyFeature Cluster was not set.","messagePattern":"The IReverseProxyFeature Cluster was not set\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Delegation/HttpSysDelegatorMiddleware.cs","lineNumber":45,"sourceCode":"        ArgumentNullException.ThrowIfNull(next);\n        ArgumentNullException.ThrowIfNull(logger);\n        ArgumentNullException.ThrowIfNull(delegator);\n        ArgumentNullException.ThrowIfNull(randomFactory);\n        _next = next;\n        _logger = logger;\n        _delegator = delegator;\n        _randomFactory = randomFactory;\n    }\n\n    public 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        var cluster = reverseProxyFeature.Cluster\n            ?? throw new InvalidOperationException($\"The {nameof(IReverseProxyFeature)} Cluster was not set.\");\n\n        if (destinations.Any())\n        {\n            // This logic mimics behavior in ForwarderMiddleware, except we save the chosen destination back\n            // to the proxy feature to ensure a delegation destination doesn't slip past this middleware.\n            var destination = destinations[0];\n            if (destinations.Count > 1)\n            {\n                var random = _randomFactory.CreateRandomInstance();\n                Log.MultipleDestinationsAvailable(_logger, reverseProxyFeature.Cluster.Config.ClusterId);\n                destination = destinations[random.Next(destinations.Count)];\n                reverseProxyFeature.AvailableDestinations = destination;\n            }\n\n            if (destination.ShouldUseHttpSysDelegation())\n            {\n                reverseProxyFeature.ProxiedDestination = destination;\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Delegation/HttpSysDelegatorMiddleware.cs#L27-L63","documentation":"Thrown by HttpSysDelegatorMiddleware.Invoke when IReverseProxyFeature.Cluster is null. The middleware needs the matched cluster to read config (e.g., ClusterId) and to proceed with delegation. A null cluster means the proxy feature was not fully initialized, usually because the route had no resolvable cluster.","triggerScenarios":"The matched route's ClusterId does not correspond to any configured cluster, or the proxy feature population stage did not run. The middleware reads reverseProxyFeature.Cluster and finds it null.","commonSituations":"Route references a ClusterId that is misspelled or missing from the Clusters config. Cluster was removed by a config reload while a request was in flight. Custom middleware interfered with feature population.","solutions":["Verify every route's ClusterId matches a defined cluster in the configuration.","Ensure the proxy feature-population middleware runs before UseHttpSysDelegation.","Validate config at startup (config validation is enabled by default) to catch dangling ClusterId references."],"exampleFix":"// before — appsettings.json\n\"Routes\": { \"r1\": { \"ClusterId\": \"clusterX\", ... } }\n// Clusters has no \"clusterX\"\n// after\n\"Clusters\": { \"clusterX\": { \"Destinations\": { ... } } }","handlingStrategy":"validation","validationCode":"var feature = context.GetReverseProxyFeature();\nif (feature.Cluster is null)\n{\n    context.Response.StatusCode = 503;\n    return;\n}","typeGuard":"static bool HasCluster(HttpContext ctx) =>\n    ctx.GetReverseProxyFeature().Cluster is not null;","tryCatchPattern":"try { await _next(context); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Cluster was not set\"))\n{ context.Response.StatusCode = 503; }","preventionTips":["Ensure every route references an existing ClusterId.","Keep config validation enabled to catch dangling references.","Order feature-population middleware before the delegator."],"tags":["middleware","delegation","cluster-config","reverse-proxy-feature"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}