biomejs/biome · error · Error

could not find any pending request matching RPC response ID

Error message

could not find any pending request matching RPC response ID ${body.id}

What it means

Each call to Transport.request() registers a resolver under an auto-incremented numeric id (nextRequestId, transport.ts:108, 130-141) in the pendingRequests map. When a JSON-RPC response arrives, its numeric id is looked up; if nothing is pending under that id the response can neither be delivered nor discarded safely, so the Transport throws (transport.ts:270-284). It means the peer sent a response the client never asked for, or asked for twice.

Source

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

			}

			if (isJsonRpcNotification(body)) {
				// TODO: Not implemented at the moment
				return;
			}

			if (isJsonRpcResponse(body)) {
				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. Create a fresh Transport (and a fresh socket) for every connection and destroy the old one on close, so stale responses can never arrive on the new instance.
  2. Upgrade daemon and client packages to matching versions if a duplicate-response bug was fixed.
  3. If you implement the server side of this protocol, always echo the request id exactly and respond exactly once per request.
  4. Treat this error as fatal for the connection: destroy the Transport and reconnect, since the stream of pending requests is now inconsistent.

Example fix

// before: one Transport shared across reconnects (id counter and pending map go stale)
let transport = new Transport(socket);
function reconnect(newSocket) {
	transport.destroy();
	transport = new Transport(newSocket);
}

// after: fresh Transport per connection, destroyed with its socket
function connect(socket) {
	const transport = new Transport(socket);
	socket.on("close", () => transport.destroy());
	return transport;
}
Defensive patterns

Strategy: validation

Validate before calling

// Keep Transport lifecycle 1:1 with the connection so pending ids can never go stale
function connect(socket) {
	const transport = new Transport(socket);
	socket.on("close", () => transport.destroy()); // no late responses on a dead socket
	return transport;
}

Try / catch

// The throw happens while processing incoming data (not inside request()'s promise), so guard globally:
process.on("uncaughtException", (err) => {
	if (err.message.includes("could not find any pending request matching RPC response ID")) {
		// Pending-request state is inconsistent; the safe recovery is a fresh connection.
		transport.destroy();
		reconnect();
	} else {
		throw err;
	}
});

Prevention

When it happens

Trigger: The server sends a duplicate response for an id that was already resolved; the server invents its own ids that do not match the client's 0-based counter; a Transport instance is reused across a reconnect while nextRequestId was reset, so late responses from the old session reference unknown ids. Note an id that is a string instead of a number fails isJsonRpcResponse (transport.ts:72-81) and produces error [4] instead.

Common situations: Reconnect logic that keeps the old socket or Transport alive; a daemon bug double-answering one request; two clients multiplexed onto one socket; version skew between client and daemon.

Related errors


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