{"record":{"id":"718c5a0d04c6e9a3","repo":"NousResearch/hermes-agent","slug":"lsp-header-block-exceeded-8-kib-without-terminator","errorCode":null,"errorMessage":"LSP header block exceeded 8 KiB without terminator","messagePattern":"LSP header block exceeded 8 KiB without terminator","errorType":"exception","errorClass":"LSPProtocolError","httpStatus":null,"severity":"error","filePath":"agent/lsp/protocol.py","lineNumber":93,"sourceCode":"    headers: dict = {}\n    header_bytes = 0\n    while True:\n        try:\n            line = await reader.readuntil(b\"\\r\\n\")\n        except asyncio.IncompleteReadError as e:\n            # EOF while reading headers.  If we hadn't started a header\n            # block, treat as clean EOF; otherwise the framing is bad.\n            if not e.partial and not headers:\n                return None\n            raise LSPProtocolError(\n                f\"unexpected EOF while reading LSP headers (partial={e.partial!r})\"\n            ) from e\n        # Defensive cap against a server streaming headers without ever\n        # emitting CRLF-CRLF.  Caps total header bytes at 8 KiB — a\n        # well-behaved server fits in well under 200 bytes.\n        header_bytes += len(line)\n        if header_bytes > 8192:\n            raise LSPProtocolError(\n                \"LSP header block exceeded 8 KiB without terminator\"\n            )\n        line = line[:-2]  # strip CRLF\n        if not line:\n            break  # blank line ends header block\n        try:\n            key, _, value = line.decode(\"ascii\").partition(\":\")\n        except UnicodeDecodeError as e:\n            raise LSPProtocolError(f\"non-ASCII LSP header: {line!r}\") from e\n        if not key:\n            raise LSPProtocolError(f\"malformed LSP header line: {line!r}\")\n        headers[key.strip().lower()] = value.strip()\n\n    cl = headers.get(\"content-length\")\n    if cl is None:\n        raise LSPProtocolError(f\"LSP message missing Content-Length: {headers!r}\")\n    try:\n        n = int(cl)","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/lsp/protocol.py#L75-L111","documentation":"LSPProtocolError from the header parser's defensive cap: the server streamed more than 8 KiB of header bytes without ever sending the CRLF-CRLF terminator that ends a header block. Well-behaved LSP headers are ~50-100 bytes, so this indicates a non-conforming or broken server output stream.","triggerScenarios":"A server (or anything sharing its stdout) writing an unbounded run of bytes without CRLF — e.g. a server printing a banner, stack trace, or progress output to stdout; a misconfigured wrapper script that forgets --stdio mode and emits interactive output.","commonSituations":"Forgetting --stdio on servers that default to IDE/interactive mode (jedi-language-server, bash-language-server variants); a wrapper (npx, docker run) printing download/progress messages to stdout; malformed Content-Length headers causing the parser to desync.","solutions":["Verify the server command includes the stdio flag (usually --stdio) so nothing human-readable goes to stdout.","Wrap the server with a shim that redirects any non-LSP stdout to stderr, or use a quieter launcher (install the binary globally instead of npx so npx prints nothing).","Check the server is a real LSP server at all — pointing the client at a plain CLI tool produces exactly this."],"exampleFix":"# before\nLSPClient(cmd=[\"npx\", \"typescript-language-server\", \"--stdio\"], ...)\n# npx may stream progress to stdout -> framing error\n\n# after\nLSPClient(cmd=[\"typescript-language-server\", \"--stdio\"], ...)  # npm i -g first","handlingStrategy":"validation","validationCode":"# smoke-test the server speaks LSP before wiring it into a session\nimport subprocess\n\ndef server_speaks_lsp(cmd: list[str], init_request: bytes) -> bool:\n    p = subprocess.run(cmd, input=init_request, capture_output=True, timeout=10)\n    return p.stdout.startswith(b\"Content-Length:\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass the server's stdio flag (usually --stdio).","Install server binaries globally instead of via npx so launchers print nothing to stdout.","Smoke-test a new server config with a handshake round-trip before enabling it."],"tags":["lsp","protocol","configuration"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}