{"record":{"id":"b042bf6fa5e3ad3d","repo":"dotnet/yarp","slug":"chosen-destination-has-no-model-set-destination","errorCode":null,"errorMessage":"Chosen destination has no model set: '{destination.DestinationId}'","messagePattern":"Chosen destination has no model set: '(.+?)'","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Forwarder/ForwarderMiddleware.cs","lineNumber":76,"sourceCode":"            activity?.AddError(\"Proxy forwarding failed\", \"No available destinations to forward to\");\n            return;\n        }\n\n        var destination = destinations[0];\n        if (destinations.Count > 1)\n        {\n            var random = _randomFactory.CreateRandomInstance();\n            Log.MultipleDestinationsAvailable(_logger, cluster.ClusterId);\n            destination = destinations[random.Next(destinations.Count)];\n        }\n\n        reverseProxyFeature.ProxiedDestination = destination;\n        activity?.AddTag(\"proxy.destination_id\", destination.DestinationId);\n\n        var destinationModel = destination.Model;\n        if (destinationModel is null)\n        {\n            throw new InvalidOperationException($\"Chosen destination has no model set: '{destination.DestinationId}'\");\n        }\n\n        try\n        {\n            cluster.ConcurrencyCounter.Increment();\n            destination.ConcurrencyCounter.Increment();\n            ForwarderTelemetry.Log.ForwarderInvoke(cluster.ClusterId, route.Config.RouteId, destination.DestinationId);\n\n            var clusterConfig = reverseProxyFeature.Cluster;\n            var result = await _forwarder.SendAsync(context, destinationModel.Config.Address, clusterConfig.HttpClient,\n                clusterConfig.Config.HttpRequest ?? ForwarderRequestConfig.Empty, route.Transformer);\n\n            activity?.SetStatus((result == ForwarderError.None) ? ActivityStatusCode.Ok : ActivityStatusCode.Error);\n        }\n        finally\n        {\n            destination.ConcurrencyCounter.Decrement();\n            cluster.ConcurrencyCounter.Decrement();","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Forwarder/ForwarderMiddleware.cs#L58-L94","documentation":"Thrown by ForwarderMiddleware.Invoke when the selected destination's Model property is null. DestinationState.Model holds the runtime DestinationConfig (address, health); a null model means the destination is in an incomplete/transitional state, e.g., it was removed during a config reload between selection and use. The forwarder cannot proceed without an address to proxy to.","triggerScenarios":"A destination is selected from AvailableDestinations but its Model is null — typically because a config reload concurrently removed/ replaced the destination, leaving a stale DestinationState in the collection. Can also indicate a bug in destination lifecycle management.","commonSituations":"High-frequency config reloads racing with in-flight requests. Custom code injecting DestinationState objects without a Model. Destinations removed dynamically while requests are being routed.","solutions":["Reduce config reload churn or batch updates to minimize the race window.","If custom-constructing DestinationState, always set Model to a valid DestinationModel.","Treat as transient: the next request after reload should succeed; add retry at the caller if needed."],"exampleFix":"// before — custom DestinationState without Model\nvar dest = new DestinationState(\"d1\"); // Model stays null\n// after\nvar dest = new DestinationState(\"d1\",\n    new DestinationModel(new DestinationConfig { Address = \"https://backend/api\" }));","handlingStrategy":"try-catch","validationCode":"if (destination.Model is null)\n{\n    context.Response.StatusCode = 503;\n    return;\n}","typeGuard":"static bool HasModel(DestinationState d) => d.Model is not null;","tryCatchPattern":"try { await _forwarder.SendAsync(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"no model set\"))\n{ context.Response.StatusCode = 503; // transient; reload race }","preventionTips":["Minimize config reload churn to reduce destination-model races.","Always set Model when constructing DestinationState programmatically.","Treat the error as transient and retry where appropriate."],"tags":["forwarder","destination","config-reload","race-condition","runtime"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}