microsoft/aspire · error · InvalidOperationException

Expected an ContainerExec resource, but got

Error message

Expected an ContainerExec resource, but got {er.DcpResourceKind} instead

What it means

This creator only knows how to turn DCP ContainerExec resources into created objects. If the rendered model resource's DcpResource is some other kind, an InvalidOperationException is thrown - an internal invariant violation indicating the resource was routed to the wrong creator.

Solutions

  1. Check the resource definition to confirm the expected DCP resource kind
  2. Upgrade Aspire.Hosting / DCP to matching versions
  3. Report as a bug if it reproduces with a standard ContainerExec resource
Defensive patterns

Strategy: type-guard

Type guard

if (rendered.DcpResource is not ContainerExec exec) throw new InvalidOperationException($"Expected ContainerExec but got {rendered.DcpResourceKind}");

Try / catch

try { await creator.CreateObjectAsync(er, ctx, logger, factory, ct); } catch (InvalidOperationException ex) when (ex.Message.Contains("ContainerExec")) { logger.LogError(ex, "Wrong creator for DCP resource kind {Kind}", er.DcpResourceKind); }

Prevention

When it happens

Trigger: A ContainerExec-typed model resource is dispatched to this creator while its underlying DCP object is a different kind (mismatch between DcpResourceKind and expected ContainerExec).

Common situations: Almost always an Aspire/DCP internal bug or version mismatch between the model builder and DCP object factory rather than user error.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting/Dcp/ContainerCreator.cs:410

        await factory.CreateDcpObjectsAsync(new[] { dcpContainer }, cToken).ConfigureAwait(false);

        var containerExes = _appResources.Get().OfType<RenderedModelResource<ContainerExec>>().Where(ar => ar.DcpResource.Spec.ContainerName == dcpContainer.Metadata.Name).ToArray();
        if (containerExes.Length > 0)
        {
            IObjectCreator<ContainerExec, EmptyCreationContext> containerExecCreator = this;
            await factory.CreateRenderedResourcesAsync(containerExecCreator, containerExes, EmptyCreationContext.s_instance, cToken).ConfigureAwait(false);
        }
    }

    bool IObjectCreator<ContainerExec, EmptyCreationContext>.IsReadyToCreate(RenderedModelResource<ContainerExec> resource, EmptyCreationContext context)
        => true;

    async Task IObjectCreator<ContainerExec, EmptyCreationContext>.CreateObjectAsync(RenderedModelResource<ContainerExec> er, EmptyCreationContext context, ILogger _, IDcpObjectFactory factory, CancellationToken cancellationToken)
    {
        if (er.DcpResource is not ContainerExec containerExe)
        {
            throw new InvalidOperationException($"Expected an {nameof(ContainerExec)} resource, but got {er.DcpResourceKind} instead");
        }

        await factory.CreateDcpObjectsAsync([containerExe], cancellationToken).ConfigureAwait(false);
    }

    internal IEnumerable<ContainerNetworkService> CreateContainerNetworkServicesForHostResource(HostResourceWithEndpoints re)
    {
        var resourceLogger = _loggerService.GetLogger(re.Resource);
        var services = new List<ContainerNetworkService>();
        var useTunnel = _options.Value.EnableAspireContainerTunnel;
        string tunnelProxyName = useTunnel ? GetTunnelProxyResourceName() : "";

        foreach (var endpoint in re.Endpoints)
        {
            var (serviceName, isNew) = _nameGenerator.GetServiceName(re.Resource, endpoint, KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
            if (!isNew)
            {
                continue;

View on GitHub (pinned to 25830f84bd)