oraios/serena · critical · LanguageServerTerminatedException

Process terminated while trying to read response (read {len(

Error message

Process terminated while trying to read response (read {len(data)} of {num_bytes} bytes before termination)

What it means

LanguageServerTerminatedException raised in _read_bytes_from_process (src/solidlsp/ls_process.py:580) when the process's stdout ends before the expected number of bytes of an LSP message could be read. It means the language server died mid-response.

Source

Thrown at src/solidlsp/ls_process.py:580

            self._process = None

    @staticmethod
    def _safely_close_pipe(pipe: IO[AnyStr] | None) -> None:
        """Safely close a pipe, ignoring any exceptions."""
        if pipe and not pipe.closed:
            try:
                pipe.close()
            except Exception:
                pass

    def _read_bytes_from_process(self, process: ManagedSubprocess[bytes], stream: IO[bytes], num_bytes: int) -> bytes:
        """Read exactly num_bytes from process stdout"""
        data = b""
        while len(data) < num_bytes:
            chunk = stream.read(num_bytes - len(data))
            if not chunk:
                if process.poll() is not None:
                    raise LanguageServerTerminatedException(
                        f"Process terminated while trying to read response (read {len(data)} of {num_bytes} bytes before termination)",
                        ls_id=self.ls_id,
                    )
                # Process still running but no data available yet, retry after a short delay
                time.sleep(0.01)
                continue
            data += chunk
        return data

    def _read_ls_process_stdout(self) -> None:
        """
        Continuously read from the language server process stdout and handle the messages
        invoking the registered response and notification handlers
        """
        exception: Exception | None = None
        try:
            while self._process and self._process.stdout:
                if self._process.poll() is not None:  # process has terminated

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Check the language server's stderr output for the crash reason (look at logs around the failure).
  2. Restart the language server session and retry the request.
  3. Reduce workload size (open smaller files, limit indexed paths) to avoid OOM crashes.
  4. Update or switch the language server version — known crash bugs are common.

Example fix

// before
symbols = ls.request_document_symbols(large_file)
// after
try:
    symbols = ls.request_document_symbols(large_file)
except LanguageServerTerminatedException:
    ls = start_fresh_server()
    symbols = ls.request_document_symbols(large_file)
Defensive patterns

Strategy: retry

Validate before calling

def server_alive(ls) -> bool:
    return ls.process is not None and ls.process.poll() is None

Type guard

def is_ls_terminated(exc: BaseException) -> bool:
    return isinstance(exc, LanguageServerTerminatedException)

Try / catch

try:
    result = ls.request_definition(path, line, col)
except LanguageServerTerminatedException:
    ls.restart()
    result = ls.request_definition(path, line, col)

Prevention

When it happens

Trigger: A pending request (e.g. request_document_symbols, request_definition) whose response never arrives because the server process crashed or was killed while reading the message header/body.

Common situations: Server out-of-memory on very large files; server segfault on unsupported constructs; OOM-killer or timeout killing the subprocess; server crashing during bulk indexing.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/4d4168d7a6d3f9c4. Report an issue: GitHub.