microsoft/aspire · error · InvalidOperationException

Failed to parse template version from stdout.

Error message

Failed to parse template version from stdout.

What it means

DotNetCliRunner's template-version parsing expects 'dotnet new' output to contain a parseable template version; when stdout does not match, it logs the failure and throws InvalidOperationException because returning a zero exit code with no version would mask a possible .NET SDK behavior change.

Solutions

  1. Check which .NET SDK version is installed (dotnet --version) and test the underlying 'dotnet new' command manually to inspect its output format.
  2. Verify the Aspire templates are installed (dotnet new install Aspire.Templates) and the SDK is a supported version.
  3. If the SDK output format changed, update the parsing logic in DotNetCliRunner to match the new format.
  4. Ensure the process is not running under a locale/culture that localizes SDK output, or set DOTNET_CLI_UI_LANGUAGE=en.

Example fix

// before (assuming old format)
// parser expected: "Template Name (aspire) vX.Y.Z"
// after: update regex to match new SDK output shape, e.g.
var match = Regex.Match(stdout, @"version\s+(?<version>[0-9.]+)");
Defensive patterns

Strategy: try-catch

Validate before calling

// Run the SDK command and check output format before relying on the parsed version
var psi = new ProcessStartInfo("dotnet", "new --list");
var stdout = await Process.Start(psi)!.StandardOutput.ReadToEndAsync();
if (!stdout.Contains("aspire"))
    throw new InvalidOperationException("Aspire templates not present or SDK output format changed.");

Try / catch

try
{
    var (exitCode, version) = await runner.GetNewTemplatesDefaultVersionAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("template version"))
{
    logger.LogError(ex, "Could not parse template version; check .NET SDK version and output format.");
}

Prevention

When it happens

Trigger: Running the new/template listing command where the SDK stdout layout changed (SDK upgrade), localized SDK output, empty stdout due to the command failing silently, or output redirection losing lines.

Common situations: After installing a new .NET SDK version whose 'dotnet new' output format differs; non-English locale emitting translated SDK messages; ASP.NET/Aspire template packs missing or partially installed.

Understand the failure class

Related errors


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

Appendix: source

Thrown at src/Aspire.Cli/DotNet/DotNetCliRunner.cs:1145

            if (stdout is null)
            {
                logger.LogError("Failed to read stdout from the process. This should never happen.");
                return (CliExitCodes.FailedToInstallTemplates, null);
            }

            // NOTE: This parsing logic is hopefully temporary and in the future we'll
            //       have structured output:
            //
            //       See: https://github.com/dotnet/sdk/issues/46345
            //
            if (!TryParsePackageVersionFromStdout(stdout, out var parsedVersion))
            {
                logger.LogError("Failed to parse template version from stdout.");

                // Throwing here because this should never happen - we don't want to return
                // the zero exit code if we can't parse the version because its possibly a
                // signal that the .NET SDK has changed.
                throw new InvalidOperationException(ErrorStrings.FailedToParseTemplateVersionFromStdout);
            }

            return (exitCode, parsedVersion);
        }
    }

    private async Task UninstallTemplateAsync(string packageName, DirectoryInfo workingDirectory, CancellationToken cancellationToken)
    {
        var exitCode = await ExecuteAsync(
            args: ["new", "uninstall", packageName],
            env: new Dictionary<string, string>
            {
                [KnownConfigNames.DotnetCliUiLanguage] = "en-US"
            },
            projectFile: null,
            workingDirectory: workingDirectory,
            backchannelCompletionSource: null,
            options: new ProcessInvocationOptions

View on GitHub (pinned to 25830f84bd)