microsoft/aspire · error · InvalidOperationException

Resource ' ' can have multiple replicas, and it uses…

Error message

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.

What it means

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.

Solutions

  1. Remove the targetPort argument so each replica's port is allocated dynamically.
  2. Reduce replicas to 1 if a fixed target port is genuinely required (e.g. external contract on that port).
  3. Let the app read ASPNETCORE_URLS/dynamic port injection instead of a fixed listen port.

Example fix

// before
builder.AddProject<Projects.Api>("api").WithEndpoint("http", e => e.TargetPort = 5000).WithReplicas(3);
// after
builder.AddProject<Projects.Api>("api").WithEndpoint("http").WithReplicas(3);
Defensive patterns

Strategy: validation

Validate before calling

if (resource.GetReplicaCount() > 1)
{
    var pinned = resource.Annotations.OfType<EndpointAnnotation>()
        .Any(e => e.TargetPort is int);
    if (pinned) throw new InvalidOperationException($"{resource.Name}: TargetPort is not allowed with replicas.");
}

Try / catch

try
{
    app.Run();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("must have a unique port"))
{
    // remove TargetPort or reduce replicas
}

Prevention

When it happens

Trigger: Resource configured with WithReplicas(n>1) plus a proxied endpoint whose TargetPort is set (e.g. WithEndpoint(..., targetPort: 5000)), detected in AddServicesProducedInfo via HasMultipleReplicas.

Common situations: Scaling out a project after hardcoding its Kestrel/launchSettings port into WithEndpoint(targetPort:...); migrating single-instance config to replicas without removing fixed target ports.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/14950e3f4a00b1ff. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/Dcp/DcpModelUtilities.cs:86

                {
                    if (HasMultipleReplicas(appResource.DcpResource))
                    {
                        throw new InvalidOperationException($"Resource '{modelResourceName}' uses multiple replicas and a proxy-less endpoint '{ea.Name}'. These features do not work together.");
                    }
                }
                else
                {
                    Debug.Assert(ea.IsProxied);

                    if (ea.TargetPort is int && ea.Port is int && ea.TargetPort == ea.Port)
                    {
                        throw new InvalidOperationException(
                            $"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.");
                    }

                    if (HasMultipleReplicas(appResource.DcpResource) && ea.TargetPort is int)
                    {
                        throw new InvalidOperationException(
                            $"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.");
                    }
                }
            }

            var spAnn = new ServiceProducerAnnotation(sp.Service.Metadata.Name);
            (spAnn.Address, _) = NormalizeTargetHost(ea.TargetHost);
            spAnn.Port = ea.TargetPort;
            appResource.DcpResource.AnnotateAsObjectList(CustomResource.ServiceProducerAnnotation, spAnn);
            appResource.ServicesProduced.Add(sp);
        }

        static bool HasMultipleReplicas(CustomResource resource)
        {
            if (resource is Executable exe && exe.Metadata.Annotations.TryGetValue(CustomResource.ResourceReplicaCount, out var value) && int.TryParse(value, CultureInfo.InvariantCulture, out var replicas) && replicas > 1)
            {
                return true;
            }

View on GitHub (pinned to 25830f84bd)