{"record":{"id":"c845022926f3ddc5","repo":"biomejs/biome","slug":"incoming-message-from-the-remote-workspace-is-miss","errorCode":null,"errorMessage":"incoming message from the remote workspace is missing the Content-Length header","messagePattern":"incoming message from the remote workspace is missing the Content-Length header","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@biomejs/backend-jsonrpc/src/transport.ts","lineNumber":213,"sourceCode":"\t\t\t\tthis.pendingData = this.pendingData.subarray(\n\t\t\t\t\tthis.readerState.contentLength,\n\t\t\t\t);\n\t\t\t\tthis.processIncomingBody(body);\n\n\t\t\t\tthis.readerState = {\n\t\t\t\t\tkind: ReaderStateKind.Header,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processIncomingHeader(readerState: ReaderStateHeader, line: string) {\n\t\tif (line === \"\\r\\n\") {\n\t\t\tconst { contentLength, contentType } = readerState;\n\t\t\tif (typeof contentLength !== \"number\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"incoming message from the remote workspace is missing the Content-Length header\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.readerState = {\n\t\t\t\tkind: ReaderStateKind.Body,\n\t\t\t\tcontentLength,\n\t\t\t\tcontentType,\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\n\t\tconst colonIndex = line.indexOf(\":\");\n\t\tif (colonIndex < 0) {\n\t\t\tthrow new Error(`could not find colon token in \"${line}\"`);\n\t\t}\n\n\t\tconst headerName = line.substring(0, colonIndex);","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/biomejs/biome/blob/7529811358079edb5a2a9d4a5f67a9f639a63f3a/packages/@biomejs/backend-jsonrpc/src/transport.ts#L195-L231","documentation":"The Transport class in @biomejs/backend-jsonrpc speaks the LSP-style JSON-RPC wire protocol over a socket: each message is preceded by a header block terminated by a blank \\r\\n line, and Content-Length tells the reader how many body bytes follow (transport.ts:209-224). When the blank line arrives but the reader state never recorded a Content-Length value (typeof contentLength !== \"number\"), the framer has no way to know the body size and throws this error. In practice it means the bytes on the socket are not framed the way this Transport expects.","triggerScenarios":"The peer writes a header block ending in \\r\\n without a Content-Length header; the socket is connected to a process that is not the Biome daemon (HTTP server, raw JSON stream, REPL banner); or an earlier framing desync causes arbitrary bytes to be interpreted as a header block. Triggered from processIncomingHeader, reached via the socket 'data' handler registered in the Transport constructor (transport.ts:117-119).","commonSituations":"Pointing the Transport at the wrong port or socket path; a version mismatch where the daemon's wire format changed; a proxy or wrapper injecting bytes into the stream; a custom mock daemon in tests that writes JSON bodies without headers.","solutions":["Verify the socket is connected to the actual Biome daemon (correct host/port/socket path), not to an HTTP endpoint or other service.","Log raw chunks on the socket and confirm every message is framed as 'Content-Length: <n>\\r\\nContent-Type: application/vscode-jsonrpc;charset=utf-8\\r\\n\\r\\n<json body>' exactly like sendMessage does (transport.ts:164-170).","Align versions: use a @biomejs/backend-jsonrpc (or @biomejs/js-api / daemon client) whose protocol matches the running daemon.","If you implement the peer yourself, always write a Content-Length header whose value is the byte length of the body before writing the body."],"exampleFix":"// before: peer writes the JSON body with no headers\nsocket.write(Buffer.from(JSON.stringify(message)));\n\n// after: peer frames the message like Transport.sendMessage does\nconst body = Buffer.from(JSON.stringify(message));\nconst headers = Buffer.from(\n\t`Content-Length: ${body.length}\\r\\nContent-Type: application/vscode-jsonrpc;charset=utf-8\\r\\n\\r\\n`,\n);\nsocket.write(Buffer.concat([headers, body]));","handlingStrategy":"validation","validationCode":"// Peek at the first chunk BEFORE constructing Transport, to verify the peer speaks the header framing\nfunction assertPeerFraming(socket) {\n\treturn new Promise((resolve, reject) => {\n\t\tsocket.once(\"data\", (chunk) => {\n\t\t\tconst head = chunk.toString(\"utf-8\", 0, 128);\n\t\t\tif (/^Content-Length:\\s*\\d+/i.test(head)) {\n\t\t\t\tresolve(socket);\n\t\t\t} else {\n\t\t\t\tsocket.destroy();\n\t\t\t\treject(new Error(`peer does not speak the JSON-RPC framing protocol, got: ${JSON.stringify(head)}`));\n\t\t\t}\n\t\t});\n\t});\n}","typeGuard":null,"tryCatchPattern":"// The throw happens inside the socket 'data' handler, so it surfaces as an uncaught exception.\n// Catch it there and fail the connection instead of the process:\nprocess.on(\"uncaughtException\", (err) => {\n\tif (err.message.includes(\"missing the Content-Length header\")) {\n\t\ttransport.destroy();\n\t\treconnect();\n\t} else {\n\t\tthrow err;\n\t}\n});","preventionTips":["Pin @biomejs/backend-jsonrpc (or the js-api client) and the daemon to matching versions so framing never changes under you.","Never point the Transport at an unverified port/socket; probe the first bytes for 'Content-Length:' before wiring it up.","If you implement the peer, frame exactly like sendMessage: Content-Length from the Buffer byte length, CRLF line endings, vscode-jsonrpc content type.","Add an integration test that round-trips one request/response through the socket to catch framing regressions early."],"tags":["jsonrpc","transport","protocol","headers","socket"],"backgroundTag":"jsonrpc-header-framing","analyzedSha":"7529811358079edb5a2a9d4a5f67a9f639a63f3a","analyzedAt":"2026-08-16T22:13:27.842Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}