microsoft/aspire · error · InvalidOperationException

The executable launch recipe for resource

Error message

The executable launch recipe for resource '{resource.Name}' returned a {plan.Mechanism} plan after {decision.Mechanism} was selected.

What it means

The launch policy makes an up-front decision (e.g., Ide or Process) about the launch mechanism, and the recipe's CreateLaunchPlanAsync must honor it. When the produced plan's Mechanism differs from the selected decision.Mechanism, this InvalidOperationException is thrown — a contract violation between the policy and the recipe implementation.

Solutions

  1. Fix the recipe implementation so CreateLaunchPlanAsync returns a plan whose Mechanism matches context/decision.Mechanism
  2. Remove or replace the custom launch recipe annotation with the standard one for the resource type
  3. Check integration package versions for a known fix and upgrade Aspire.Hosting/integrations together

Example fix

// before (custom recipe)
return new ExecutableLaunchPlan { Mechanism = ExecutableLaunchMechanism.Process, ... }; // policy chose Ide
// after
return new ExecutableLaunchPlan { Mechanism = decision.Mechanism, ... };
Defensive patterns

Strategy: validation

Validate before calling

var decision = launchPolicy.Decide(resource);
var context = new ExecutableLaunchContext(resource, decision, resourceLogger, cancellationToken);
var plan = await recipe.CreateLaunchPlanAsync(context);
if (plan.Mechanism != decision.Mechanism)
    throw new InvalidOperationException("Recipe returned a mismatched launch mechanism.");

Type guard

bool MechanismMatches(ExecutableLaunchPlan p, LaunchDecision d) => p.Mechanism == d.Mechanism;

Try / catch

try
{
    await creator.CreateObjectAsync(renderedResource, resourceLogger, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("plan after"))
{
    // Recipe/policy contract violation — fix or replace the custom launch recipe.
}

Prevention

When it happens

Trigger: A custom or buggy ExecutableLaunchRecipeAnnotation recipe whose CreateLaunchPlanAsync returns a plan with a different ExecutableLaunchMechanism than the one the launch policy decided (e.g., policy selected Ide but recipe returned Process).

Common situations: Custom launch recipes that ignore the decision context; integration packages with incompatible recipe implementations; switching run modes (Run vs publish/IDE attach) with a recipe not honoring the mechanism.

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/0b7118e16b7c9fc4. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/Dcp/ExecutableCreator.cs:146

        {
            throw new InvalidOperationException(
                $"Resource '{resource.Name}' must have exactly one executable launch recipe, but {recipes.Length} were found.");
        }

        var decision = launchPolicy.Decide(resource);
        var context = new ExecutableLaunchContext(
            resource,
            configuration,
            distributedApplicationOptions,
            executionConfiguration,
            decision,
            resourceLogger,
            cancellationToken);
        var plan = await recipes[0].Recipe.CreateLaunchPlanAsync(context).ConfigureAwait(false);

        if (plan.Mechanism != decision.Mechanism)
        {
            throw new InvalidOperationException(
                $"The executable launch recipe for resource '{resource.Name}' returned a {plan.Mechanism} plan after {decision.Mechanism} was selected.");
        }

        if (plan.Mechanism == ExecutableLaunchMechanism.Ide && plan.LaunchConfigurations.Count == 0)
        {
            throw new InvalidOperationException(
                $"The executable launch recipe for resource '{resource.Name}' selected IDE execution without producing a launch configuration.");
        }

        return plan;
    }

    internal static void Render(
        RenderedModelResource<Executable> renderedResource,
        ExecutableLaunchPlan plan,
        ExecutablePemCertificates? pemCertificates,
        ILogger logger)
    {

View on GitHub (pinned to 25830f84bd)