NousResearch/hermes-agent · error · LSPProtocolError

truncated LSP body: expected {n} bytes, got {len(e.partial)}

Error message

truncated LSP body: expected {n} bytes, got {len(e.partial)}

What it means

LSPProtocolError raised when readexactly(n) — reading the Content-Length-declared body — hits EOF after only len(e.partial) bytes. The server promised n bytes but died or closed stdout before delivering them, so the JSON body is incomplete and cannot be parsed.

Source

Thrown at agent/lsp/protocol.py:120

            raise LSPProtocolError(f"non-ASCII LSP header: {line!r}") from e
        if not key:
            raise LSPProtocolError(f"malformed LSP header line: {line!r}")
        headers[key.strip().lower()] = value.strip()

    cl = headers.get("content-length")
    if cl is None:
        raise LSPProtocolError(f"LSP message missing Content-Length: {headers!r}")
    try:
        n = int(cl)
    except ValueError as e:
        raise LSPProtocolError(f"non-integer Content-Length: {cl!r}") from e
    if n < 0 or n > 64 * 1024 * 1024:  # 64 MiB sanity cap
        raise LSPProtocolError(f"unreasonable Content-Length: {n}")

    try:
        body = await reader.readexactly(n)
    except asyncio.IncompleteReadError as e:
        raise LSPProtocolError(
            f"truncated LSP body: expected {n} bytes, got {len(e.partial)}"
        ) from e

    try:
        return json.loads(body.decode("utf-8"))
    except json.JSONDecodeError as e:
        raise LSPProtocolError(f"invalid JSON in LSP body: {e}") from e
    except UnicodeDecodeError as e:
        raise LSPProtocolError(f"non-UTF-8 LSP body: {e}") from e


def make_request(req_id: int, method: str, params: Any) -> dict:
    """Build a JSON-RPC 2.0 request envelope."""
    msg: dict = {"jsonrpc": "2.0", "id": req_id, "method": method}
    if params is not None:
        msg["params"] = params
    return msg

View on GitHub (pinned to c896c09c42)

Solutions

  1. Restart the client and server, then re-open documents to retrigger the work — a mid-body death is a server crash, and stderr (drained at debug level) usually names the exception.
  2. Raise memory/ulimits for the server process if it dies on large payloads.
  3. If one specific file reliably kills the server, exclude it or update the server — report the crash upstream.
Defensive patterns

Strategy: retry

Try / catch

try:
    msg = await read_message(reader)
except LSPProtocolError as e:
    if "truncated LSP body" in str(e):
        client = await restart_client_and_reopen_docs(client)  # server died mid-write
        msg = await read_message(reader)
    else:
        raise

Prevention

When it happens

Trigger: Server killed (OOM, signal) mid-write of a large response; server crashing while serializing a huge diagnostics payload; process exiting abruptly after sending headers (e.g. unhandled exception after write of headers but before body flush).

Common situations: Memory limits on containers running clangd/rust-analyzer with big workspaces; servers crashing on specific pathological files; forced shutdowns during heavy indexing.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/c4c5c669c356500c. Report an issue: GitHub.