microsoft/aspire · error · InvalidOperationException
Duplicate step name
Error message
Duplicate step name: '{step.Name}' What it means
The Aspire application model pipeline validates that every pipeline step has a unique name before executing. During ResolveStepsAsync, ValidateSteps adds each step name to an ordinal HashSet; a duplicate add means two steps registered with the same name, which would make dependency references ambiguous, so an InvalidOperationException is thrown before any step runs.
Solutions
- Find the second registration of the step with the duplicated name and remove it or guard it so it runs only once
- Make step names unique by incorporating the resource/identifier, e.g. $"{resource.Name}-deploy" instead of a constant
- If an extension method may be called multiple times, have it check whether a step with that name already exists before adding
- Update the dependency references (DependsOnSteps/RequiredBySteps) that pointed at the old shared name to point at the new unique names
Example fix
// before
builder.Pipeline.AddStep("deploy", ...);
foreach (var r in resources) { builder.Pipeline.AddStep("deploy", ...); }
// after
foreach (var r in resources) { builder.Pipeline.AddStep($"deploy-{r.Name}", ...); } Defensive patterns
Strategy: validation
Validate before calling
var names = new HashSet<string>(StringComparer.Ordinal);
foreach (var step in pipeline.Steps)
{
if (!names.Add(step.Name))
throw new InvalidOperationException($"Duplicate step name registered: '{step.Name}'");
} Try / catch
try { await app.RunAsync(); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Duplicate step name:"))
{
// fix the duplicated step registration indicated in ex.Message
} Prevention
- Generate step names from resource names ($"{resource.Name}-{purpose}") instead of constants
- Before adding a step, check whether a step with the same name already exists and skip/reuse it
- Keep step registration in one central place to avoid accidental double registration
- Search your codebase for AddStep/DependsOn calls with the same literal name
When it happens
Trigger: Two or more IHostingPipelineStep implementations (or AddStep calls) registered with the identical Name string into the same DistributedApplicationPipeline; also occurs when an integration is added twice (e.g. two AddXxx calls each contributing a step with the same fixed name) or a step is registered per-resource with a constant name instead of including the resource name.
Common situations: Calling an integration extension method twice on the same builder when it unconditionally adds a fixed-name step; copying sample code that adds the same custom step twice; a loop over resources that registers a step named after the type rather than the resource; two different packages each contributing a step with a colliding name.
Related errors
- Step ' ' depends on unknown step
- Step ' ' is required by unknown step
- AzureSandboxOptions.AutoDeleteEnabled must be set when…
- AzureSandboxOptions.AutoSuspendEnabled must be set when…
- Circular dependency detected in pipeline steps
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/8b1f8c2539240bc5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs:815
Model = pipelineContext.Model
};
foreach (var callback in callbacks)
{
await callback(configContext).ConfigureAwait(false);
}
}
}
private static void ValidateSteps(IEnumerable<PipelineStep> steps)
{
var stepNames = new HashSet<string>(StringComparer.Ordinal);
foreach (var step in steps)
{
if (!stepNames.Add(step.Name))
{
throw new InvalidOperationException(
$"Duplicate step name: '{step.Name}'");
}
}
foreach (var step in steps)
{
foreach (var dependency in step.DependsOnSteps)
{
if (!stepNames.Contains(dependency))
{
throw new InvalidOperationException(
$"Step '{step.Name}' depends on unknown step '{dependency}'");
}
}
foreach (var requiredBy in step.RequiredBySteps)
{
if (!stepNames.Contains(requiredBy))View on GitHub (pinned to 25830f84bd)