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
- Call WithImage("<image>") before WithImageTag/WithImageRegistry/WithImageSHA256 in the builder chain.
- If the container is built from a Dockerfile, use WithDockerfile-related APIs instead of image annotation APIs.
- Reorder the fluent chain so WithImage appears first.
- 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
- Always start container resource chains with WithImage (or WithDockerfile).
- In shared builder helpers, assert the image annotation exists before mutating image settings.
- When refactoring fluent chains, keep WithImage as the first image-related call.
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
- Ambiguous tags - a tag was provided on both the 'tag' and…
- invalid digest format
- RemoteImageName must be set.
- Tag conflicts with digest provided on the 'image' parameter
- A circular lifetime reference was detected for resource
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)