github/copilot-sdk · critical · IOException

CLI process exited unexpectedly.

Error message

CLI process exited unexpectedly.

What it means

When starting the CLI in stdio mode, waitForPortAnnouncement reads stdout lines waiting for the CLI to announce its TCP port. If stdout closes (readLine returns null) before a port line is seen, the CLI process has terminated, so the manager throws IOException (augmented with captured stderr via formatCliExitedMessage).

Solutions

  1. Catch the IOException and read the attached stderr output to find the CLI's actual failure reason.
  2. Verify cliPath points to a working, executable CLI binary (`<path> --version`).
  3. Reinstall/update the Copilot CLI to a compatible version.
  4. Check environment constraints (sandbox, permissions, architecture) that could kill the process.

Example fix

// before
JsonRpcClient client = manager.startCliServer();
// after
try {
    JsonRpcClient client = manager.startCliServer();
} catch (IOException e) {
    log.error("CLI failed to start: {}", e.getMessage()); // includes stderr
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

ProcessBuilder pb = new ProcessBuilder(cliPath, "--version");
pb.start().waitFor(10, TimeUnit.SECONDS); // fail fast if binary is broken

Try / catch

try {
  client = manager.startCliServer();
} catch (IOException e) {
  // e.getMessage() includes CLI stderr — surface it to the user
  throw new StartupException("CLI failed: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: startCliServer spawns the CLI process, but the process exits during startup — bad CLI path, missing executable permissions, corrupted install, crashing CLI, or fatal startup error printed to stderr.

Common situations: Wrong cliPath pointing to a non-CLI binary; CLI crashes on unsupported OS/arch or missing dependencies; stderr shows auth or config fatal errors; CLI killed by the environment (OOM, sandbox).

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/e64191421f2269f8. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/CliServerManager.java:199

            }
        }, "cli-stderr-reader");
        thread.setDaemon(true);
        thread.start();
        this.stderrThread = thread;
    }

    private Integer waitForPortAnnouncement(Process process) throws IOException {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
            Pattern portPattern = Pattern.compile("listening on port (\\d+)", Pattern.CASE_INSENSITIVE);
            long deadline = System.currentTimeMillis() + 30000;

            while (System.currentTimeMillis() < deadline) {
                String line = reader.readLine();
                if (line == null) {
                    awaitStderrReader();
                    String stderr = getStderrOutput();
                    throw new IOException(formatCliExitedMessage("CLI process exited unexpectedly.", stderr));
                }

                Matcher matcher = portPattern.matcher(line);
                if (matcher.find()) {
                    return Integer.parseInt(matcher.group(1));
                }
            }

            process.destroyForcibly();
            throw new IOException("Timeout waiting for CLI to announce port");
        }
    }

    String getStderrOutput() {
        synchronized (stderrBuffer) {
            return stderrBuffer.toString().trim();
        }
    }

View on GitHub (pinned to cd8cf15dc3)