microsoft/aspire · error · InvalidOperationException
Failed to start child process
Error message
Failed to start child process: {startInfo.FileName} What it means
StartRedirected launches a child via System.Diagnostics.Process.Start with redirected stdio. .NET's Process.Start returns null (rather than throwing) when the underlying CreateProcess call fails, and this code converts that null into an InvalidOperationException naming the executable. The most common underlying cause is the executable file not existing at the given path.
Solutions
- Verify startInfo.FileName exists and is executable: run `where <name>` (Windows) or `command -v <name>` (Unix) in the same environment.
- Use an absolute path for FileName instead of relying on PATH resolution.
- Confirm the WorkingDirectory exists and is accessible; a bad working directory fails spawn regardless of a valid FileName.
- Check PATH in the exact environment the CLI runs in (CI containers, VS Code terminals, services) and add the tool's directory.
- Install/repair the missing tool (e.g. run the Aspire CLI setup so dcp is provisioned).
Example fix
// before startInfo.FileName = "dcp"; // after startInfo.FileName = "/home/user/.aspire/bin/dcp/dcp"; // resolved absolute path // (or ensure the directory containing the executable is on PATH before starting)
Defensive patterns
Strategy: validation
Validate before calling
// Validate the executable and working directory before Start
var exePath = ResolveExecutable(fileName); // search PATH or use absolute path
if (exePath is null || !File.Exists(exePath))
{
throw new FileNotFoundException($"Executable '{fileName}' was not found. Install it or add its directory to PATH.");
}
if (workingDirectory is not null && !Directory.Exists(workingDirectory))
{
throw new DirectoryNotFoundException($"Working directory '{workingDirectory}' does not exist.");
} Try / catch
try
{
var process = isolatedProcess.Start(startInfo);
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Failed to start child process:"))
{
// FileName didn't resolve — verify PATH / installation before retrying
} Prevention
- Always use absolute executable paths or verify the tool is on PATH in the exact run environment.
- Check that WorkingDirectory exists, especially in CI where checkout dirs differ.
- Provision required tools (dcp, dotnet) as a pre-step in CI containers.
- Log startInfo.FileName and WorkingDirectory on failure to speed diagnosis.
When it happens
Trigger: StartAsync routes to StartRedirected (non-detached, redirected stdio path), Process.Start(psi) returns null for startInfo.FileName — typically because FileName doesn't resolve (bad path, missing extension, not on PATH) or the working directory is invalid.
Common situations: Typing a wrong executable name/path in apphost configuration, a tool (dcp, dotnet, docker) not installed or not on PATH, running the CLI from a directory where a relative WorkingDirectory no longer exists, or a PATH stripped in CI containers.
Related errors
- Failed to start DCP fork-process.
- Foundry CLI command ' ' could not be started.
- Unable to start 'cargo' to inspect the Rust app
- An absolute path is required
- Aspire skills bundle contains an empty relative path.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/cb2f9f198becdf58.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Processes/IsolatedProcess.cs:396
// Pin encodings so process output decoding is stable regardless of the ambient
// Console.OutputEncoding (e.g. on container hosts that leave it set to ASCII).
StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),
StandardErrorEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),
};
foreach (var arg in startInfo.ArgumentList)
{
psi.ArgumentList.Add(arg);
}
// Only mutate the ProcessStartInfo env block when the caller actually touched
// IsolatedProcessStartInfo.Environment. Otherwise leave ProcessStartInfo to inherit
// the parent's env verbatim — saves a snapshot-and-copy round trip for the common
// case where nothing was customized.
ProcessEnvironment.ApplyTo(psi, startInfo.GetEnvironmentForSpawn());
var process = Process.Start(psi)
?? throw new InvalidOperationException($"Failed to start child process: {startInfo.FileName}");
process.StandardInput.Close();
return new StartedProcess(
process,
process.StandardOutput,
process.StandardError,
ExtraDispose: null);
}
/// <summary>
/// Applies the already-started process and platform-specific handle/readers to this wrapper.
/// </summary>
private void InitializeStartedProcess(StartedProcess startedProcess)
{
_process = startedProcess.Process;
_id = startedProcess.ProcessId ?? startedProcess.Process.Id;
Arguments = _startInfo.ArgumentList.ToArray();View on GitHub (pinned to 25830f84bd)