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
- 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.
- Upgrade daemon and client packages to matching versions if a duplicate-response bug was fixed.
- If you implement the server side of this protocol, always echo the request id exactly and respond exactly once per request.
- 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
- Never reuse a Transport instance across reconnects; its id counter and pending map belong to one connection.
- Destroy the Transport whenever the underlying socket closes so late responses cannot be parsed.
- If you implement the peer, always echo the request id exactly and respond at most once per request.
- Run daemon and client packages from the same release so response-id behavior matches.
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
- incoming message from the remote workspace is missing the Co
- could not find colon token in "${line}"
- invalid value for Content-Type expected "${MIME_JSONRPC}", g
- failed to deserialize incoming message from remote workspace
AI-assisted analysis of biomejs/biome@7529811358 (2026-08-16).
Data as JSON: /api/errors/cee25925125be784.
Report an issue: GitHub.