microsoft/aspire · error · ArgumentException
The requiredBy parameter must be a string or IEnumerable
Error message
The requiredBy parameter must be a string or IEnumerable<string>, but was {requiredBy.GetType().Name}. What it means
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.
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.
Example fix
// before
var step = new PipelineStep("deploy") { RequiredBy = 'publish' };
// after
var step = new PipelineStep("deploy") { RequiredBy = new[] { "publish" } }; Defensive patterns
Strategy: type-guard
Validate before calling
bool IsValidRequiredBy(object? requiredBy) =>
requiredBy is string or IEnumerable<string>; Type guard
static bool IsStringOrStringEnumerable(object? value) =>
value is string || (value is IEnumerable<object> seq && seq.All(item => item is string)); Try / catch
try
{
pipeline.AddStep(step);
}
catch (ArgumentException ex) when (ex.ParamName == nameof(requiredBy))
{
logger.LogError(ex, "requiredBy must be string or IEnumerable<string>, was {Type}", step.RequiredBy?.GetType().Name);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A step with the name
- Step ' ' is required by unknown step
- Step ' ' not found in pipeline. Available steps
- The container registry configured for the Azure Cognitive…
- Unsupported completion state.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/d6c2c40a1bb64396.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Pipelines/DistributedApplicationPipeline.cs:522
}
}
private static void AddRequiredBy(PipelineStep step, object requiredBy)
{
if (requiredBy is string stepName)
{
step.RequiredBy(stepName);
}
else if (requiredBy is IEnumerable<string> stepNames)
{
foreach (var name in stepNames)
{
step.RequiredBy(name);
}
}
else
{
throw new ArgumentException(
$"The requiredBy parameter must be a string or IEnumerable<string>, but was {requiredBy.GetType().Name}.",
nameof(requiredBy));
}
}
public void AddStep(PipelineStep step)
{
if (_steps.Any(s => s.Name == step.Name))
{
throw new InvalidOperationException(
$"A step with the name '{step.Name}' has already been added to the pipeline.");
}
_steps.Add(step);
}
public void AddPipelineConfiguration(Func<PipelineConfigurationContext, Task> callback)
{View on GitHub (pinned to 25830f84bd)