microsoft/aspire · error · ArgumentNullException

Array params contains null item

Error message

Array params contains null item: [{values}]

What it means

ThrowIfNullOrContainsIsNullOrEmpty throws ArgumentNullException when the string[] args parameter passed to DistributedApplicationTestingBuilder.CreateAsync/Create contains a null element. The message lists all args to make the offending array easy to diagnose.

Solutions

  1. Filter nulls before calling: args.Where(a => a is not null).ToArray()
  2. Ensure every element is a non-empty string like "--key=value"
  3. Validate args with the same null/empty check in test helper code

Example fix

// before
await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>(new[] { "--feature", null });
// after
var args = new[] { "--feature", "on" }.Where(a => !string.IsNullOrEmpty(a)).ToArray();
await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>(args);
Defensive patterns

Strategy: validation

Validate before calling

if (args.Any(a => a is null)) throw new InvalidOperationException("args contains null items");

Type guard

static string[] WithoutNulls(string?[] args) => args.Where(a => a is not null).ToArray()!;

Try / catch

try { await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>(args); }
catch (ArgumentNullException ex) when (ex.ParamName == "args")
{
    // sanitize args and retry
}

Prevention

When it happens

Trigger: Calling DistributedApplicationTestingBuilder.CreateAsync<T>(new string[] { null }) or passing an array built dynamically that contains a null entry (e.g. from a dictionary value or optional CLI argument that was null).

Common situations: Building args from config where a value is null; spreading a list with trailing nulls; passing (string[]?) variables without checking.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/a41c000f768be9e2. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Testing/DistributedApplicationTestingBuilder.cs:448

            // test and CI output, so withhold the live browser credential from each while keeping their endpoint
            // lines. The ASPIRE_DASHBOARD-prefixed value is copied to the child process by DashboardEventHandlers.
            // Tests get the credential through GetDashboardUrlAsync instead.
            ["AppHost:SuppressDashboardLoginUrlInStartupSummary"] = "true",
            [KnownConfigNames.DashboardSuppressBrowserTokenInOutput] = "true"
        });
    }

    private static void ThrowIfNullOrContainsIsNullOrEmpty(string[] args)
    {
        ArgumentNullException.ThrowIfNull(args);
        foreach (var arg in args)
        {
            if (string.IsNullOrEmpty(arg))
            {
                var values = string.Join(", ", args);
                if (arg is null)
                {
                    throw new ArgumentNullException(nameof(args), $"Array params contains null item: [{values}]");
                }
                throw new ArgumentException($"Array params contains empty item: [{values}]", nameof(args));
            }
        }
    }

    /// <summary>
    /// The dashboard testing configuration resolved during builder construction. Carried as a single value so the
    /// pre-construction and post-construction halves of the configuration cannot drift apart.
    /// </summary>
    private readonly record struct DashboardTestingState(bool Enabled, string? BrowserToken, string? ResourceServiceApiKey);

    private sealed class SuspendingDistributedApplicationFactory(
        Type entryPoint,
        string[] args,
        DistributedApplicationTestingBuilderOptions? testingOptions,
        Action<DistributedApplicationOptions, HostApplicationBuilderSettings> configureBuilder)
        : DistributedApplicationFactory(entryPoint, args)

View on GitHub (pinned to 25830f84bd)