microsoft/aspire · error · InvalidOperationException
Resource ' ' uses multiple replicas and a persistent…
Error message
Resource '{resource.Name}' uses multiple replicas and a persistent lifetime. These features do not work together. What it means
A resource configured with both a persistent lifetime (survives AppHost restarts, e.g. dcpdev / with persistent lifetime) and more than one replica is rejected: persistent resources are keyed to stable names/ports, which replicas cannot share. The check runs in ThrowIfPersistentExecutableHasReplicas when DCP instances are populated.
Solutions
- Remove WithReplicas(n) (or set to 1) on resources using persistent lifetime.
- Set the lifetime back to the default (e.g. WithLifetime(Lifetime.Session) or drop the persistent-lifetime flag) if replicas are needed.
- Split the app: keep the persistent single instance for iteration and a separate session-lifetime resource for scaled scenarios.
Example fix
// before
builder.AddProject<Projects.Worker>("worker")
.WithLifetime(Lifetime.Persistent)
.WithReplicas(3);
// after
builder.AddProject<Projects.Worker>("worker")
.WithLifetime(Lifetime.Session)
.WithReplicas(3); Defensive patterns
Strategy: validation
Validate before calling
if (resource.GetReplicaCount() > 1 && resource.GetLifetimeType() == Lifetime.Persistent)
throw new InvalidOperationException($"{resource.Name}: persistent lifetime is incompatible with multiple replicas."); Try / catch
try
{
app.Run();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("multiple replicas and a persistent lifetime"))
{
// drop replicas or switch back to session lifetime
} Prevention
- Audit WithReplicas calls before enabling persistent lifetime globally (e.g. aspire run with persistent resources).
- Document that persistent-lifetime resources must stay single-instance in team conventions.
- Centralize lifetime configuration so replicas and lifetime are set together consistently.
When it happens
Trigger: Executable (or container) resource with Lifetime.Persistent (e.g. via WithLifetime(Lifetime.Persistent) or the dcpdev/persistent-lifetime feature) plus GetReplicaCount() > 1 from WithReplicas, during EnsureDcpInstancesPopulated.
Common situations: Combining the persistent-lifetime dev-loop feature (fast restarts) with scaled-out replicas; enabling persistent lifetime globally without realizing it conflicts with WithReplicas in some projects.
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
- Resource ' ' can have multiple replicas, and it uses…
- Resource ' ' uses multiple replicas and a proxy-less…
- Cannot allocate temporary files after the service has been…
- Container tunnel service
- Couldn't find required instance ID for index
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/f3602725c3ebe5ce.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Dcp/DcpNameGenerator.cs:81
AddInstancesAnnotation(resource, builder.ToImmutable());
}
}
private static void AddInstancesAnnotation(IResource resource, ImmutableArray<DcpInstance> instances)
{
resource.Annotations.Add(new DcpInstancesAnnotation(instances));
}
private static void ThrowIfPersistentExecutableHasReplicas(IResource resource)
{
if (resource is not (ExecutableResource or ProjectResource))
{
return;
}
if (resource.GetReplicaCount() > 1 && resource.GetLifetimeType() == Lifetime.Persistent)
{
throw new InvalidOperationException($"Resource '{resource.Name}' uses multiple replicas and a persistent lifetime. These features do not work together.");
}
}
public (string Name, string Suffix) GetContainerName(IResource container)
{
var nameSuffix = container.GetLifetimeType() switch
{
Lifetime.Session => GetRandomNameSuffix(),
_ => GetProjectHashSuffix(),
};
return (GetObjectNameForResource(container, _options.Value, nameSuffix), nameSuffix);
}
public (string Name, string Suffix) GetExecutableName(IResource project)
{
var nameSuffix = project.GetLifetimeType() switch
{View on GitHub (pinned to 25830f84bd)