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
- Verify the devtunnel CLI is installed: run 'devtunnel --version' in a terminal
- Set ASPIRE_DEVTUNNEL_CLI_PATH to the absolute path of a working devtunnel executable
- On Linux/macOS, ensure the binary has the execute bit (chmod +x)
- 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
- Install the devtunnel CLI and verify with 'devtunnel --version' before starting the AppHost
- Pin ASPIRE_DEVTUNNEL_CLI_PATH to an absolute path in CI
- Check execute permissions on Linux/macOS after extracting the CLI
- Exclude the CLI directory from antivirus/scanner interference
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
- CLI path must be provided
- Failed to delete port
- Failed to get access details for
- Failed to get devtunnel CLI version. Output
- Failed to get user login status. Exit code
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)