github/copilot-sdk · error · IOException
CLI process exited unexpectedly. stderr
Error message
CLI process exited unexpectedly.
stderr: {stderrOutput} What it means
StartAsync wraps an unexpected CLI process exit in an IOException that appends the collected stderr output. When the child CLI process dies during startup or operation and its stderr contains diagnostics, the library rethrows as 'CLI process exited unexpectedly.\nstderr: ...' with the original exception as the inner exception, so the underlying failure reason is preserved in the stderr text.
Solutions
- Read the 'stderr:' section of the message - it contains the actual crash reason from the CLI.
- Verify the CLI is installed, executable, and a version compatible with the SDK.
- Run the CLI manually with the same arguments to reproduce and inspect the failure.
- Retry via EnsureConnectedAsync after fixing the underlying cause; check innerException for the original exit details.
Example fix
// before
var client = new CopilotClient(options, RuntimeConnection.ForStdio()); // old CLI version crashes on startup
// after
// 1. inspect stderr in the IOException message
try { await client.StartAsync(); }
catch (IOException ex) { Console.WriteLine(ex.Message); } // shows CLI stderr
// 2. update the CLI to a compatible version, then retry Defensive patterns
Strategy: try-catch
Validate before calling
// verify the CLI runs before connecting:
var psi = new ProcessStartInfo(cliPath, "--version") { RedirectStandardError = true };
using var p = Process.Start(psi);
if (p is null || p.WaitForExit(5000) && p.ExitCode != 0)
throw new InvalidOperationException("CLI is not healthy before start."); Type guard
null
Try / catch
try { await client.StartAsync(); }
catch (IOException ex) when (ex.Message.StartsWith("CLI process exited unexpectedly"))
{
var stderr = ex.Message[(ex.Message.IndexOf("stderr:") + 7)..];
logger.LogError(ex, "CLI crashed. stderr: {Stderr}", stderr);
} Prevention
- Pin a CLI version compatible with the SDK
- Check CLI installation and dependencies in environment setup
- Capture and log stderr on every startup failure
- Add a health-check step that runs 'cli --version' before connecting
When it happens
Trigger: Calling StartAsync/EnsureConnectedAsync (or any operation over an active session) when the spawned CLI process crashes or exits early; the stderr pump buffer is non-empty and the exception is not already a stderr-formatted message.
Common situations: Unsupported or corrupt CLI installation; missing runtime dependencies for the CLI binary; port conflicts or startup crashes printed to stderr; the CLI being killed by the OS; version mismatch between SDK and CLI.
Related errors
- Communication error with Copilot CLI
- CLI process exited unexpectedly
- CLI process exited unexpectedly.
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
- Runtime process not started
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/3effe0d67bbaa378.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:515
if (connection is not null)
{
await CleanupConnectionAsync(connection, errors: null, gracefulRuntimeShutdown: false);
}
else if (cliProcess is not null)
{
await CleanupCliProcessAsync(cliProcess, stderrPump, errors: null, _logger);
}
if (ex is IOException
&& cliProcess is not null
&& stderrPump is not null
&& !ex.Message.Contains("stderr:", StringComparison.OrdinalIgnoreCase))
{
var stderrOutput = GetStderrOutput(stderrPump.Buffer);
if (!string.IsNullOrEmpty(stderrOutput))
{
throw new IOException(
FormatCliExitedMessage("CLI process exited unexpectedly.", stderrOutput),
ex);
}
}
throw;
}
}
}
/// <summary>
/// Disconnects from the Copilot server and closes all active sessions.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
/// <remarks>
/// <para>
/// This method performs graceful cleanup:
/// <list type="number">View on GitHub (pinned to cd8cf15dc3)