{"record":{"id":"14950e3f4a00b1ff","repo":"microsoft/aspire","slug":"resource-modelresourcename-can-have-multiple-replicas-and-it","errorCode":null,"errorMessage":"Resource '{modelResourceName}' can have multiple replicas, and it uses endpoint '{ea.Name}' that has TargetPort property set. Each replica must have a unique port; setting TargetPort is not allowed.","messagePattern":"Resource '(.+?)' can have multiple replicas, and it uses endpoint '(.+?)' that has TargetPort property set\\. Each replica must have a unique port; setting TargetPort is not allowed\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Dcp/DcpModelUtilities.cs","lineNumber":86,"sourceCode":"                {\n                    if (HasMultipleReplicas(appResource.DcpResource))\n                    {\n                        throw new InvalidOperationException($\"Resource '{modelResourceName}' uses multiple replicas and a proxy-less endpoint '{ea.Name}'. These features do not work together.\");\n                    }\n                }\n                else\n                {\n                    Debug.Assert(ea.IsProxied);\n\n                    if (ea.TargetPort is int && ea.Port is int && ea.TargetPort == ea.Port)\n                    {\n                        throw new InvalidOperationException(\n                            $\"The endpoint '{ea.Name}' for resource '{modelResourceName}' requested a proxy ({nameof(ea.IsProxied)} is true). Non-container resources cannot be proxied when both {nameof(ea.TargetPort)} and {nameof(ea.Port)} are specified with the same value.\");\n                    }\n\n                    if (HasMultipleReplicas(appResource.DcpResource) && ea.TargetPort is int)\n                    {\n                        throw new InvalidOperationException(\n                            $\"Resource '{modelResourceName}' can have multiple replicas, and it uses endpoint '{ea.Name}' that has {nameof(ea.TargetPort)} property set. Each replica must have a unique port; setting {nameof(ea.TargetPort)} is not allowed.\");\n                    }\n                }\n            }\n\n            var spAnn = new ServiceProducerAnnotation(sp.Service.Metadata.Name);\n            (spAnn.Address, _) = NormalizeTargetHost(ea.TargetHost);\n            spAnn.Port = ea.TargetPort;\n            appResource.DcpResource.AnnotateAsObjectList(CustomResource.ServiceProducerAnnotation, spAnn);\n            appResource.ServicesProduced.Add(sp);\n        }\n\n        static bool HasMultipleReplicas(CustomResource resource)\n        {\n            if (resource is Executable exe && exe.Metadata.Annotations.TryGetValue(CustomResource.ResourceReplicaCount, out var value) && int.TryParse(value, CultureInfo.InvariantCulture, out var replicas) && replicas > 1)\n            {\n                return true;\n            }","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dcp/DcpModelUtilities.cs#L68-L104","documentation":"When a resource can run multiple replicas and a proxied endpoint has an explicit TargetPort, every replica would bind the same target port, which is impossible because each replica must get a unique port. Aspire disallows TargetPort on endpoints of multi-replica resources.","triggerScenarios":"Resource configured with WithReplicas(n>1) plus a proxied endpoint whose TargetPort is set (e.g. WithEndpoint(..., targetPort: 5000)), detected in AddServicesProducedInfo via HasMultipleReplicas.","commonSituations":"Scaling out a project after hardcoding its Kestrel/launchSettings port into WithEndpoint(targetPort:...); migrating single-instance config to replicas without removing fixed target ports.","solutions":["Remove the targetPort argument so each replica's port is allocated dynamically.","Reduce replicas to 1 if a fixed target port is genuinely required (e.g. external contract on that port).","Let the app read ASPNETCORE_URLS/dynamic port injection instead of a fixed listen port."],"exampleFix":"// before\nbuilder.AddProject<Projects.Api>(\"api\").WithEndpoint(\"http\", e => e.TargetPort = 5000).WithReplicas(3);\n// after\nbuilder.AddProject<Projects.Api>(\"api\").WithEndpoint(\"http\").WithReplicas(3);","handlingStrategy":"validation","validationCode":"if (resource.GetReplicaCount() > 1)\n{\n    var pinned = resource.Annotations.OfType<EndpointAnnotation>()\n        .Any(e => e.TargetPort is int);\n    if (pinned) throw new InvalidOperationException($\"{resource.Name}: TargetPort is not allowed with replicas.\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    app.Run();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"must have a unique port\"))\n{\n    // remove TargetPort or reduce replicas\n}","preventionTips":["Never hardcode targetPort on projects you plan to scale with WithReplicas.","Prefer environment-injected dynamic ports (ASPNETCORE_URLS) for scaled services.","Add a team convention check/lint on endpoint annotations for multi-replica resources."],"tags":["aspire","dcp","replicas","targetport","endpoint"],"backgroundTag":"conflicting-config-options","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}