{"record":{"id":"69e54607b0e61ba2","repo":"microsoft/aspire","slug":"a-step-with-the-name-step-name-has-already-been-added-to-the","errorCode":null,"errorMessage":"A step with the name '{step.Name}' has already been added to the pipeline.","messagePattern":"A step with the name '(.+?)' has already been added to the pipeline\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs","lineNumber":532,"sourceCode":"        {\n            foreach (var name in stepNames)\n            {\n                step.RequiredBy(name);\n            }\n        }\n        else\n        {\n            throw new ArgumentException(\n                $\"The requiredBy parameter must be a string or IEnumerable<string>, but was {requiredBy.GetType().Name}.\",\n                nameof(requiredBy));\n        }\n    }\n\n    public void AddStep(PipelineStep step)\n    {\n        if (_steps.Any(s => s.Name == step.Name))\n        {\n            throw new InvalidOperationException(\n                $\"A step with the name '{step.Name}' has already been added to the pipeline.\");\n        }\n\n        _steps.Add(step);\n    }\n\n    public void AddPipelineConfiguration(Func<PipelineConfigurationContext, Task> callback)\n    {\n        ArgumentNullException.ThrowIfNull(callback);\n        _configurationCallbacks.Add(callback);\n    }\n\n    /// <summary>\n    /// Creates a clone of this pipeline whose built-in steps are independent\n    /// copies (with fresh <see cref=\"PipelineStep.DependsOnSteps\"/> /\n    /// <see cref=\"PipelineStep.RequiredBySteps\"/> and final action lists).\n    /// Configuration callbacks are shallow-copied — the same delegates are reused.\n    /// </summary>","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs#L514-L550","documentation":"AddStep enforces that each PipelineStep in a DistributedApplicationPipeline has a unique name. If a step with the same name (compared as an exact match against already-registered steps) is added a second time, the pipeline throws this InvalidOperationException rather than silently overwriting or duplicating the step, since duplicate names would make dependency resolution ambiguous.","triggerScenarios":"Calling pipeline.AddStep(step) when a step whose Name equals step.Name has already been added - e.g., calling AddStep twice for the same step instance, registering the same step in both a base and a derived configuration, or re-running registration code in a loop without unique names.","commonSituations":"Configuring pipelines in a loop where the step name is not parameterized; calling AddStep from multiple extension methods that each register the same infrastructure step (e.g., both a 'push' and 'deploy' helper adding a 'build' step); test setup methods invoked multiple times on a shared pipeline instance.","solutions":["Guard the call: only call AddStep if the step name is not already present, e.g., use pipeline.TryAddStep if available or check _steps/known names first.","Give each step a unique, descriptive name (e.g., prefix with the owning feature: 'frontend-build' vs 'backend-build').","Move duplicate-prone registration into an idempotent helper that dedupes by name before adding.","In tests, create a fresh DistributedApplicationPipeline instance per test instead of reusing one in a shared fixture."],"exampleFix":"// before\npipeline.AddStep(new PipelineStep(\"build\"));\npipeline.AddStep(new PipelineStep(\"build\")); // throws\n// after\nif (pipeline.Steps.All(s => s.Name != \"build\"))\n{\n    pipeline.AddStep(new PipelineStep(\"build\"));\n}","handlingStrategy":"validation","validationCode":"if (pipeline.Steps.Any(s => s.Name == step.Name))\n{\n    throw new InvalidOperationException($\"Step '{step.Name}' is already registered.\");\n}\npipeline.AddStep(step);","typeGuard":null,"tryCatchPattern":"try\n{\n    pipeline.AddStep(step);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"has already been added\"))\n{\n    logger.LogWarning(\"Step {StepName} already registered; skipping duplicate.\", step.Name);\n}","preventionTips":["Build registration helpers that dedupe by step name before calling AddStep.","Use unique, feature-prefixed step names in shared infrastructure code.","Create a new pipeline instance per test/operation instead of reusing one.","Keep a single canonical registration site per well-known step."],"tags":["duplicate-key","pipeline","registration","csharp"],"backgroundTag":"file-already-exists","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"}