microsoft/aspire · error · InvalidOperationException

The endpoint ' ' for container resource ' ' must specify…

Error message

The endpoint '{endpoint.Name}' for container resource '{modelResourceName}' must specify the TargetPort value

What it means

When mapping Aspire model endpoints to DCP service annotations, DcpModelUtilities validates that every endpoint on a container resource has a concrete TargetPort. Containers do not get a dynamically assigned port inside the container, so a container endpoint without TargetPort has nothing to bind to, and Aspire throws InvalidOperationException at validation time.

Solutions

  1. Pass targetPort to WithEndpoint/WithHttpEndpoint on the container resource.
  2. Remember the distinction: for containers, targetPort = the port the app listens on inside the container.
  3. Set the environment variable (e.g. ASPNETCORE_HTTP_PORTS) in the container to match the targetPort.
  4. Use a typed endpoint helper (WithHttpEndpoint(port: ...)) that forces the port argument.

Example fix

// before
var cache = builder.AddContainer("cache", "redis", "latest")
    .WithHttpEndpoint();
// after
var cache = builder.AddContainer("cache", "redis", "latest")
    .WithHttpEndpoint(port: 6379, targetPort: 6379);
Defensive patterns

Strategy: validation

Validate before calling

static void EnsureContainerEndpointHasTargetPort(IResource resource, EndpointAnnotation e)
{
    if (resource.IsContainer() && EndpointAnnotation.NormalizePort(e.TargetPort) is null)
        throw new InvalidOperationException($"Endpoint '{e.Name}' on container '{resource.Name}' needs a TargetPort.");
}

Type guard

static bool HasTargetPort(EndpointAnnotation e) => EndpointAnnotation.NormalizePort(e.TargetPort) is not null;

Try / catch

try { await builder.Build().RunAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must specify the TargetPort"))
{
    // fix the endpoint registration on the named container resource
}

Prevention

When it happens

Trigger: Calling WithEndpoint/WithHttpEndpoint/WithHttpsEndpoint (or WithEndpoint<T>) on a container resource without supplying targetPort, e.g. builder.AddContainer("x","img").WithHttpEndpoint() with no port argument, then running/publishing the AppHost.

Common situations: Copying project-style endpoint code (where targetPort is optional) onto containers; refactoring a project resource into a container and forgetting to add the container-side port; forgetting that for containers the 'port' is the in-container listening port.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting/Dcp/DcpModelUtilities.cs:39

    internal static bool ShouldDeferCreateForExplicitStart(IResource modelResource, bool? start)
    {
        // Explicit-start, non-persistent resources use manual snapshots for dashboard visibility.
        // Do not create corresponding DCP objects until the manual start path flips Spec.Start=true; creation
        // evaluates callbacks that can prompt for input or depend on start-time state.
        return start == false &&
            modelResource.TryGetLastAnnotation<ExplicitStartupAnnotation>(out _) &&
            modelResource.GetLifetimeType() != Lifetime.Persistent;
    }

    internal static void ValidateEndpointPorts(IResource modelResource, EndpointAnnotation endpoint)
    {
        var modelResourceName = modelResource.Name ?? "(unknown)";

        if (modelResource.IsContainer())
        {
            if (EndpointAnnotation.NormalizePort(endpoint.TargetPort) is null)
            {
                throw new InvalidOperationException($"The endpoint '{endpoint.Name}' for container resource '{modelResourceName}' must specify the {nameof(EndpointAnnotation.TargetPort)} value");
            }
        }
        else if (!endpoint.IsProxied && endpoint.Port is int && endpoint.Port != endpoint.TargetPort)
        {
            throw new InvalidOperationException($"The endpoint '{endpoint.Name}' for resource '{modelResourceName}' is not using a proxy, and it has a value of {nameof(EndpointAnnotation.Port)} property that is different from the value of {nameof(EndpointAnnotation.TargetPort)} property. For proxy-less endpoints they must match.");
        }
    }

    /// <summary>
    /// Examines the Aspire resource annotations and adds equivalent ServiceProducerAnnotations to the corresponding DCP resource.
    /// </summary>
    internal static void AddServicesProducedInfo<TDcpResource>(
        RenderedModelResource<TDcpResource> appResource,
        IEnumerable<IAppResource> appResources)
        where TDcpResource : CustomResource, IKubernetesStaticMetadata
    {
        var modelResource = appResource.ModelResource;
        var modelResourceName = modelResource.Name ?? "(unknown)";

View on GitHub (pinned to 25830f84bd)