biomejs/biome · error · Error

failed to deserialize incoming message from remote workspace

Error message

failed to deserialize incoming message from remote workspace, "${data}" is not a valid JSON-RPC message body

What it means

After a body frame is extracted and JSON.parse succeeds (a SyntaxError from JSON.parse at transport.ts:257 is a different failure), the parsed object is validated against the JSON-RPC 2.0 shapes: it must have jsonrpc === "2.0" (isJsonRpcMessage) and match a request, notification, or response guard (transport.ts:33-92). If none match, the message is unusable and this error is thrown with the raw body embedded (transport.ts:289-291).

Source

Thrown at packages/@biomejs/backend-jsonrpc/src/transport.ts:289

				const pendingRequest = this.pendingRequests.get(body.id);
				if (pendingRequest) {
					this.pendingRequests.delete(body.id);
					const { resolve, reject } = pendingRequest;
					if ("result" in body) {
						resolve(body.result);
					} else {
						reject(body.error);
					}
				} else {
					throw new Error(
						`could not find any pending request matching RPC response ID ${body.id}`,
					);
				}
				return;
			}
		}

		throw new Error(
			`failed to deserialize incoming message from remote workspace, "${data}" is not a valid JSON-RPC message body`,
		);
	}
}

View on GitHub (pinned to 7529811358)

Solutions

  1. Inspect the data string included in the error message to see exactly what envelope the peer actually sent.
  2. Fix the sender to emit full JSON-RPC 2.0 envelopes: jsonrpc: "2.0", numeric ids, and result or error on responses.
  3. When framing outgoing messages, set Content-Length to the Buffer byte length of the body, not the JS string length.
  4. Verify the connected process is the Biome daemon and its version matches the client package.

Example fix

// before: peer answers with a bare JSON object
socket.write(frame({ status: "ok" }));

// after: peer answers with a JSON-RPC 2.0 envelope echoing the request id
socket.write(frame({ jsonrpc: "2.0", id: requestId, result: { status: "ok" } }));
Defensive patterns

Strategy: validation

Validate before calling

// Peer-side guard: validate every outgoing frame is a JSON-RPC 2.0 envelope with byte-accurate framing
function frame(message) {
	if (message.jsonrpc !== "2.0") throw new Error("outgoing message must carry jsonrpc: '2.0'");
	if ("method" in message && typeof message.id === "number") {
		// request: fine
	} else if ("method" in message) {
		// notification: fine
	} else if (typeof message.id === "number" && ("result" in message || "error" in message)) {
		// response: fine
	} else {
		throw new Error("outgoing message matches no JSON-RPC 2.0 shape");
	}
	const body = Buffer.from(JSON.stringify(message));
	return Buffer.concat([Buffer.from(`Content-Length: ${body.length}\r\n\r\n`), body]);
}

Type guard

// Mirrors the receiver's guards (transport.ts:33-92)
function isJsonRpcResponse(message) {
	return (
		typeof message === "object" &&
		message !== null &&
		message.jsonrpc === "2.0" &&
		typeof message.id === "number" &&
		!("method" in message) &&
		("result" in message || "error" in message)
	);
}

Try / catch

process.on("uncaughtException", (err) => {
	if (err.message.includes("is not a valid JSON-RPC message body")) {
		// The peer's envelope is wrong; log the embedded body and fail the connection.
		transport.destroy();
	} else {
		throw err;
	}
});

Prevention

When it happens

Trigger: The peer sends valid JSON that is not JSON-RPC 2.0: missing 'jsonrpc': '2.0' envelope; a response with a string id; a message with neither result nor error; or a truncated/concatenated body caused by an incorrect Content-Length that happens to still parse as JSON.

Common situations: The socket is wired to a plain JSON service instead of the daemon; Content-Length computed from UTF-16 string length instead of byte length truncates multi-byte messages; a daemon/client version mismatch changes the message envelope.

Related errors


AI-assisted analysis of biomejs/biome@7529811358 (2026-08-16). Data as JSON: /api/errors/7d49e409702cf6c8. Report an issue: GitHub.