microsoft/aspire · error · InvalidOperationException

Cannot set entrypoint: Python environment annotation with…

Error message

Cannot set entrypoint: Python environment annotation with virtual environment not found.

What it means

WithEntrypoint lets you change a Python app's entrypoint after creation, but it needs the VirtualEnvironment stored in PythonEnvironmentAnnotation (typically set by a prior WithVirtualEnvironment call) to compute the new command. If the annotation is missing or its VirtualEnvironment is null, it throws InvalidOperationException.

Solutions

  1. Call WithVirtualEnvironment before WithEntrypoint so the PythonEnvironmentAnnotation is populated.
  2. Confirm the earlier WithVirtualEnvironment call succeeded (no swallowed exception).
  3. Verify you are calling WithEntrypoint on the same resource builder that has the virtual environment configured.
  4. If no venv is intended, use the base app APIs (AddPythonApp) instead of WithEntrypoint.

Example fix

// before
var py = builder.AddPythonApp("app", "main.py");
py.WithEntrypoint(EntrypointType.Script, "other.py"); // missing venv
// after
var py = builder.AddPythonApp("app", "main.py");
py.WithVirtualEnvironment(".venv");
py.WithEntrypoint(EntrypointType.Script, "other.py");
Defensive patterns

Strategy: type-guard

Validate before calling

bool venvReady = pyApp.Resource.TryGetLastAnnotation<PythonEnvironmentAnnotation>(out var env) && env?.VirtualEnvironment is not null;

Type guard

static bool HasVirtualEnvironment(IResource resource) =>
    resource.TryGetLastAnnotation<PythonEnvironmentAnnotation>(out var env) && env.VirtualEnvironment is not null;

Try / catch

try
{
    pyApp.WithEntrypoint(EntrypointType.Script, "other.py");
}
catch (InvalidOperationException ex) when (ex.Message.Contains("virtual environment not found"))
{
    logger.LogError(ex, "Call WithVirtualEnvironment before WithEntrypoint.");
}

Prevention

When it happens

Trigger: Calling WithEntrypoint on a Python resource without first calling WithVirtualEnvironment (or after a call that failed to register PythonEnvironmentAnnotation with a non-null VirtualEnvironment).

Common situations: Changing entrypoints on resources that never got a virtual environment configured; ordering mistakes where WithEntrypoint precedes WithVirtualEnvironment in the chain; failed WithVirtualEnvironment setup swallowed earlier.

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

Appendix: source

Thrown at src/Aspire.Hosting.Python/PythonAppResourceBuilderExtensions.cs:1046

    /// Change a Python app from running a script to running a module:
    /// <code lang="csharp">
    /// var python = builder.AddPythonScript("api", "../python-api", "main.py")
    ///     .WithEntrypoint(EntrypointType.Module, "uvicorn")
    ///     .WithArgs("main:app", "--reload");
    /// </code>
    /// </example>
    [AspireExport]
    public static IResourceBuilder<T> WithEntrypoint<T>(
        this IResourceBuilder<T> builder, EntrypointType entrypointType, string entrypoint) where T : PythonAppResource
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrEmpty(entrypoint);

        // Get or create the virtual environment from the annotation
        if (!builder.Resource.TryGetLastAnnotation<PythonEnvironmentAnnotation>(out var pythonEnv) ||
            pythonEnv.VirtualEnvironment is null)
        {
            throw new InvalidOperationException("Cannot set entrypoint: Python environment annotation with virtual environment not found.");
        }

        var virtualEnvironment = pythonEnv.VirtualEnvironment;

        // Determine the new command based on entrypoint type
        var command = entrypointType switch
        {
            EntrypointType.Executable => virtualEnvironment.GetExecutable(entrypoint),
            EntrypointType.Script or EntrypointType.Module => virtualEnvironment.GetExecutable("python"),
            _ => throw new ArgumentOutOfRangeException(nameof(entrypointType), entrypointType, "Invalid entrypoint type.")
        };

        // Update the command inline
        builder.WithCommand(command);
        builder.WithAnnotation(new PythonEntrypointAnnotation
        {
            Type = entrypointType,
            Entrypoint = entrypoint

View on GitHub (pinned to 25830f84bd)