{"record":{"id":"d6c2c40a1bb64396","repo":"microsoft/aspire","slug":"the-requiredby-parameter-must-be-a-string-or-ienumerable","errorCode":null,"errorMessage":"The requiredBy parameter must be a string or IEnumerable<string>, but was {requiredBy.GetType().Name}.","messagePattern":"The requiredBy parameter must be a string or IEnumerable<string>, but was (.+?)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs","lineNumber":522,"sourceCode":"        }\n    }\n\n    private static void AddRequiredBy(PipelineStep step, object requiredBy)\n    {\n        if (requiredBy is string stepName)\n        {\n            step.RequiredBy(stepName);\n        }\n        else if (requiredBy is IEnumerable<string> stepNames)\n        {\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    {","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs#L504-L540","documentation":"The pipeline's AddRequiredBy helper (invoked from AddStep) accepts only a single step name (string) or a collection of step names (IEnumerable<string>) for the 'requiredBy' parameter. Passing any other object type (e.g., a char, a single-element non-enumerable type, or a boxed value) is rejected with this ArgumentException because the library cannot interpret it as step-name data. It is a defensive argument-validation failure.","triggerScenarios":"Calling DistributedApplicationPipeline.AddStep with a PipelineStep whose RequiredBy parameter was supplied as an unsupported type - e.g., a char ('a' instead of \"a\"), a HashSet, or any object not implementing IEnumerable<string> - so the type switch in AddRequiredBy falls to the else branch.","commonSituations":"Hand-writing pipeline step registrations where a single character literal is passed instead of a string; using a collection type that does not implement IEnumerable<string> (e.g., List<int> of step indexes); refactoring code that changed a string parameter to a custom type; copy-pasting requiredBy values from a config where types are loosely parsed.","solutions":["Inspect the value passed as requiredBy and ensure it is a string or an IEnumerable<string> (e.g., new[]{\"StepA\", \"StepB\"}).","If passing a single step name, add .ToString() or wrap the literal in double quotes instead of single quotes (C# char vs string).","If passing a collection of another element type, map it to strings first: requiredBy.Select(x => x.ToString()).","Check whether a config deserializer produced a non-string type (e.g., JValue, JsonElement) and convert with value.GetValue<string>() or value.ToString() before calling AddStep."],"exampleFix":"// before\nvar step = new PipelineStep(\"deploy\") { RequiredBy = 'publish' };\n// after\nvar step = new PipelineStep(\"deploy\") { RequiredBy = new[] { \"publish\" } };","handlingStrategy":"type-guard","validationCode":"bool IsValidRequiredBy(object? requiredBy) =>\n    requiredBy is string or IEnumerable<string>;","typeGuard":"static bool IsStringOrStringEnumerable(object? value) =>\n    value is string || (value is IEnumerable<object> seq && seq.All(item => item is string));","tryCatchPattern":"try\n{\n    pipeline.AddStep(step);\n}\ncatch (ArgumentException ex) when (ex.ParamName == nameof(requiredBy))\n{\n    logger.LogError(ex, \"requiredBy must be string or IEnumerable<string>, was {Type}\", step.RequiredBy?.GetType().Name);\n}","preventionTips":["Always declare requiredBy values as string or string[] at the call site.","Avoid object-typed intermediaries for step names.","When reading names from config, materialize to strings before AddStep.","Add a unit test that exercises AddStep with each supported requiredBy shape."],"tags":["argument-validation","type-mismatch","pipeline","csharp"],"backgroundTag":"invalid-argument-value","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"}