microsoft/aspire · error · ArgumentException

Image must be a string or AddContainerOptions.

Error message

Image must be a string or AddContainerOptions.

What it means

AddContainerForPolyglot accepts the image argument as either a plain string (image name/reference) or an AddContainerOptions object. This ArgumentException is thrown for any other argument type, or an unsupported null/other value after the null check.

Solutions

  1. Pass the image as a string such as "docker.io/library/redis:latest".
  2. Alternatively construct and pass an AddContainerOptions instance.
  3. Check the dynamic language binding so the argument is marshalled as string or AddContainerOptions, not an unmapped type.
  4. exampleFix placeholder

Example fix

// before
builder.AddContainerForPolyglot("cache", 42);
// after
builder.AddContainerForPolyglot("cache", "docker.io/library/redis:latest");
Defensive patterns

Strategy: type-guard

Validate before calling

if (image is not (string or AddContainerOptions))
    throw new ArgumentException("Image must be a string or AddContainerOptions.", nameof(image));

Type guard

bool IsValidImageArg(object? image) => image is string or AddContainerOptions;

Try / catch

try
{
    builder.AddContainerForPolyglot(name, image);
}
catch (ArgumentException ex)
{
    // Coerce image to string or AddContainerOptions and retry
}

Prevention

When it happens

Trigger: Calling AddContainerForPolyglot with an image argument that is neither string nor AddContainerOptions (e.g. an integer, object, or unhandled type from dynamic/polyglot code).

Common situations: Polyglot apphosts passing loosely typed image values; code generators emitting the wrong type; JS/Python wrappers marshalling the image argument incorrectly.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting/ContainerResourceBuilderExtensions.cs:165

    /// <param name="name">The name of the resource.</param>
    /// <param name="image">The image name or image options for the container.</param>
    /// <returns>The <see cref="IResourceBuilder{T}"/> for chaining.</returns>
    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport("addContainer")]
    internal static IResourceBuilder<ContainerResource> AddContainerForPolyglot(
        this IDistributedApplicationBuilder builder,
        [ResourceName] string name,
        [AspireUnion(typeof(string), typeof(AddContainerOptions))] object image)
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrEmpty(name);
        ArgumentNullException.ThrowIfNull(image);

        return image switch
        {
            string imageName => AddContainer(builder, name, imageName),
            AddContainerOptions options => AddContainer(builder, name, options),
            _ => throw new ArgumentException("Image must be a string or AddContainerOptions.", nameof(image))
        };
    }

    private static IResourceBuilder<ContainerResource> AddContainer(
        IDistributedApplicationBuilder builder,
        string name,
        AddContainerOptions options)
    {
        ArgumentNullException.ThrowIfNull(options);
        ArgumentException.ThrowIfNullOrEmpty(options.Image);

        if (options.Tag is { } tag)
        {
            ArgumentException.ThrowIfNullOrEmpty(tag);
            return AddContainer(builder, name, options.Image, tag);
        }

        return AddContainer(builder, name, options.Image);

View on GitHub (pinned to 25830f84bd)