microsoft/aspire · error · InvalidOperationException

Failed to start devtunnel process.

Error message

Failed to start devtunnel process.

What it means

DevTunnelCli.RunAsync launches the devtunnel executable and checks the boolean result of Process.Start(). If the operating system fails to spawn the process, the method throws this InvalidOperationException rather than letting the run continue with a dead process handle.

Solutions

  1. Verify the devtunnel CLI is installed: run 'devtunnel --version' in a terminal
  2. Set ASPIRE_DEVTUNNEL_CLI_PATH to the absolute path of a working devtunnel executable
  3. On Linux/macOS, ensure the binary has the execute bit (chmod +x)
  4. Check antivirus/EDR policies or sandbox restrictions that block spawning the process

Example fix

// before (appsettings/env)
ASPIRE_DEVTUNNEL_CLI_PATH=devtunnel   // not on PATH
// after
ASPIRE_DEVTUNNEL_CLI_PATH=/usr/local/bin/devtunnel
Defensive patterns

Strategy: try-catch

Validate before calling

var resolved = DevTunnelCli.GetCliPath(configuration);
if (resolved != "devtunnel" && !File.Exists(resolved))
    throw new InvalidOperationException($"devtunnel CLI not found at '{resolved}'.");

Try / catch

try
{
    await cli.GetVersionAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to start devtunnel process"))
{
    logger.LogError(ex, "Could not launch devtunnel CLI at '{Path}'. Verify install and execute permissions.", cliPath);
}

Prevention

When it happens

Trigger: Calling any DevTunnelCli operation (GetVersionAsync, CreateTunnelAsync, etc.) when Process.Start returns false — the executable path exists but the OS cannot spawn it, or the path resolved to a non-executable.

Common situations: devtunnel binary not installed or not on PATH so the resolved 'devtunnel' path is invalid; file exists but lacks execute permission (Linux/macOS); antivirus or sandbox blocking process creation; corrupted CLI download.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.DevTunnels/DevTunnelCli.cs:255

    private async Task<int> RunAsync(Action<bool, string> onOutput, string[] args, bool useShellExecute = false, ILogger? logger = default, CancellationToken cancellationToken = default)
    {
        using var process = new Process
        {
            StartInfo = BuildStartInfo(args, useShellExecute),
            EnableRaisingEvents = true
        };

        var stdoutTask = Task.CompletedTask;
        var stderrTask = Task.CompletedTask;

        logger?.LogTrace("Invoking devtunnel CLI{ShellExecuteInfo}: {FileName} {Arguments}", useShellExecute ? " (UseShellExecute=true)" : "", process.StartInfo.FileName, EscapeArgList(process.StartInfo.ArgumentList));

        try
        {
            if (!process.Start())
            {
                throw new InvalidOperationException("Failed to start devtunnel process.");
            }

            if (!useShellExecute)
            {
                stdoutTask = PumpAsync(process.StandardOutput, line => onOutput(false, line), cancellationToken);
                stderrTask = PumpAsync(process.StandardError, line => onOutput(true, line), cancellationToken);
            }

            using var ctr = cancellationToken.Register(() =>
            {
                try
                {
                    if (!process.HasExited)
                    {
                        logger?.LogTrace("Cancellation requested, killing devtunnel process tree.");
                        process.Kill(entireProcessTree: true);
                    }
                }

View on GitHub (pinned to 25830f84bd)