{"record":{"id":"cb2f9f198becdf58","repo":"microsoft/aspire","slug":"failed-to-start-child-process-startinfo-filename","errorCode":null,"errorMessage":"Failed to start child process: {startInfo.FileName}","messagePattern":"Failed to start child process: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Processes/IsolatedProcess.cs","lineNumber":396,"sourceCode":"            // Pin encodings so process output decoding is stable regardless of the ambient\n            // Console.OutputEncoding (e.g. on container hosts that leave it set to ASCII).\n            StandardOutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),\n            StandardErrorEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),\n        };\n\n        foreach (var arg in startInfo.ArgumentList)\n        {\n            psi.ArgumentList.Add(arg);\n        }\n\n        // Only mutate the ProcessStartInfo env block when the caller actually touched\n        // IsolatedProcessStartInfo.Environment. Otherwise leave ProcessStartInfo to inherit\n        // the parent's env verbatim — saves a snapshot-and-copy round trip for the common\n        // case where nothing was customized.\n        ProcessEnvironment.ApplyTo(psi, startInfo.GetEnvironmentForSpawn());\n\n        var process = Process.Start(psi)\n            ?? throw new InvalidOperationException($\"Failed to start child process: {startInfo.FileName}\");\n\n        process.StandardInput.Close();\n\n        return new StartedProcess(\n            process,\n            process.StandardOutput,\n            process.StandardError,\n            ExtraDispose: null);\n    }\n\n    /// <summary>\n    /// Applies the already-started process and platform-specific handle/readers to this wrapper.\n    /// </summary>\n    private void InitializeStartedProcess(StartedProcess startedProcess)\n    {\n        _process = startedProcess.Process;\n        _id = startedProcess.ProcessId ?? startedProcess.Process.Id;\n        Arguments = _startInfo.ArgumentList.ToArray();","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Processes/IsolatedProcess.cs#L378-L414","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nstartInfo.FileName = \"dcp\";\n// after\nstartInfo.FileName = \"/home/user/.aspire/bin/dcp/dcp\"; // resolved absolute path\n// (or ensure the directory containing the executable is on PATH before starting)","handlingStrategy":"validation","validationCode":"// Validate the executable and working directory before Start\nvar exePath = ResolveExecutable(fileName); // search PATH or use absolute path\nif (exePath is null || !File.Exists(exePath))\n{\n    throw new FileNotFoundException($\"Executable '{fileName}' was not found. Install it or add its directory to PATH.\");\n}\nif (workingDirectory is not null && !Directory.Exists(workingDirectory))\n{\n    throw new DirectoryNotFoundException($\"Working directory '{workingDirectory}' does not exist.\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var process = isolatedProcess.Start(startInfo);\n}\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Failed to start child process:\"))\n{\n    // FileName didn't resolve — verify PATH / installation before retrying\n}","preventionTips":["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."],"tags":["process","process-start","path","executable-not-found"],"backgroundTag":"command-not-found","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}