microsoft/aspire · error · InvalidOperationException

The resource ' ' does not have a container image specified…

Error message

The resource '{builder.Resource.Name}' does not have a container image specified. Use WithImage to specify the container image and tag.

What it means

Image-related APIs (WithImageTag, WithImageRegistry, WithImageSHA256) require the resource to already have a container image annotation, which is normally set by WithImage. When the annotation is missing, ThrowResourceIsNotContainer throws this InvalidOperationException because there is no image to tag, register, or digest-pin.

Solutions

  1. Call WithImage("<image>") before WithImageTag/WithImageRegistry/WithImageSHA256 in the builder chain.
  2. If the container is built from a Dockerfile, use WithDockerfile-related APIs instead of image annotation APIs.
  3. Reorder the fluent chain so WithImage appears first.
  4. exampleFix placeholder

Example fix

// before
builder.AddContainer("app", "image").WithImageTag("1.0"); // no image set
// after
builder.AddContainer("app", "image").WithImage("myrepo/myapp").WithImageTag("1.0");
Defensive patterns

Strategy: validation

Validate before calling

bool HasImage<T>(IResourceBuilder<T> builder) where T : ContainerResource =>
    builder.Resource.Annotations.OfType<ContainerImageAnnotation>().Any();
if (!HasImage(builder)) throw new InvalidOperationException("Call WithImage before WithImageTag/WithImageRegistry/WithImageSHA256.");

Type guard

bool HasImage<T>(IResourceBuilder<T> b) where T : ContainerResource =>
    b.Resource.Annotations.OfType<ContainerImageAnnotation>().Any();

Try / catch

try
{
    resource.WithImageTag("1.0");
}
catch (InvalidOperationException ex) when (ex.Message.Contains("does not have a container image"))
{
    // Add WithImage first and retry
}

Prevention

When it happens

Trigger: Calling WithImageTag/WithImageRegistry/WithImageSHA256 on a container resource builder that never had WithImage called (or on a resource created without an image).

Common situations: Refactoring that removed or reordered WithImage; building containers from Dockerfiles (WithDockerfile) and then calling image-mutating APIs; copy-pasted builder chains missing the WithImage step.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

    /// <summary>
    /// Sets the pull policy for the container resource.
    /// </summary>
    /// <typeparam name="T">The resource type.</typeparam>
    /// <param name="builder">Builder for the container resource.</param>
    /// <param name="pullPolicy">The pull policy behavior for the container resource.</param>
    /// <returns>The <see cref="IResourceBuilder{T}"/>.</returns>
    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport]
    public static IResourceBuilder<T> WithImagePullPolicy<T>(this IResourceBuilder<T> builder, ImagePullPolicy pullPolicy) where T : ContainerResource
    {
        ArgumentNullException.ThrowIfNull(builder);

        return builder.WithAnnotation(new ContainerImagePullPolicyAnnotation { ImagePullPolicy = pullPolicy }, ResourceAnnotationMutationBehavior.Replace);
    }
    private static IResourceBuilder<T> ThrowResourceIsNotContainer<T>(IResourceBuilder<T> builder) where T : ContainerResource
    {
        throw new InvalidOperationException($"The resource '{builder.Resource.Name}' does not have a container image specified. Use WithImage to specify the container image and tag.");
    }

    /// <summary>
    /// Changes the resource to be published as a container in the manifest.
    /// </summary>
    /// <param name="builder">Resource builder.</param>
    /// <returns>The <see cref="IResourceBuilder{T}"/>.</returns>
    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport]
    public static IResourceBuilder<T> PublishAsContainer<T>(this IResourceBuilder<T> builder) where T : ContainerResource
    {
        ArgumentNullException.ThrowIfNull(builder);

        return builder.WithManifestPublishingCallback(context => context.WriteContainerAsync(builder.Resource));
    }

    /// <summary>
    /// Causes Aspire to build the specified container image from a Dockerfile.

View on GitHub (pinned to 25830f84bd)