github/copilot-sdk · error · EOFError

Unexpected end of stream while reading JSON-RPC message

Error message

Unexpected end of stream while reading JSON-RPC message

What it means

_read_exact reads exactly num_bytes from the child process's stdout; if the stream returns an empty chunk before the count is satisfied, the stream ended unexpectedly and this EOFError is raised. The JSON-RPC message being read is therefore truncated and unusable.

Solutions

  1. Check the child process's stderr and exit code to find why the CLI died, and fix that root cause (bad args, missing deps).
  2. Re-run and verify a stable CLI version; reinstall the CLI/runtime if the binary is corrupt.
  3. Capture stdout/stderr in a pipe (not a terminal or file redirection that truncates).
  4. Wrap the reader in retry logic that restarts the client process after unexpected EOF.
Defensive patterns

Strategy: try-catch

Validate before calling

if process.poll() is not None:
    raise RuntimeError("CLI process already exited; check stderr before RPC")

Try / catch

try:
    msg = client.read_message()
except EOFError as e:
    if "Unexpected end of stream" in str(e):
        exit_code = process.wait(); log(process.stderr.read()); restart_client()

Prevention

When it happens

Trigger: The Copilot CLI child process exited or closed stdout mid-message — crash, kill, stdout corruption, or partial line write — while _read_message was reading the frame body.

Common situations: CLI binary crashing due to missing dependencies or bad args; process killed by OOM or signal; piping stdout somewhere that truncates output.

Related errors


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

Appendix: source

Thrown at python/copilot/_jsonrpc.py:343

    def _read_exact(self, num_bytes: int) -> bytes:
        """
        Read exactly num_bytes, handling partial/short reads from pipes.

        Args:
            num_bytes: Number of bytes to read

        Returns:
            Bytes read from stream

        Raises:
            EOFError: If stream ends before reading all bytes
        """
        chunks = []
        remaining = num_bytes
        while remaining > 0:
            chunk = self.process.stdout.read(remaining)
            if not chunk:
                raise EOFError("Unexpected end of stream while reading JSON-RPC message")
            chunks.append(chunk)
            remaining -= len(chunk)
        return b"".join(chunks)

    def _read_message(self) -> dict | None:
        """
        Read a single JSON-RPC message with a Content-Length header (blocking).

        Returns:
            Parsed JSON message, or None if the connection is closed.
        """
        # Read header line
        header_line = self.process.stdout.readline()
        if not header_line:
            return None

        # Parse Content-Length
        header = header_line.decode("utf-8").strip()

View on GitHub (pinned to cd8cf15dc3)