rust-lang/rust-analyzer · error
received response for unknown request
Error message
received response for unknown request
What it means
complete_request pops the pending-request handler registered when a request was sent to the client, keyed by response id. The .expect panics when a response arrives whose id was never registered (or was already completed/cancelled), meaning the client replied to a request rust-analyzer does not track. This is an internal protocol-queue invariant: every response must match an outstanding request.
Source
Thrown at crates/rust-analyzer/src/global_state.rs:604
flycheck: self.flycheck.clone(),
}
}
pub(crate) fn send_request<R: lsp_types::Request>(
&mut self,
params: R::Params,
handler: ReqHandler,
) {
let request = self.req_queue.outgoing.register(R::METHOD.into(), params, handler);
self.send(request.into());
}
pub(crate) fn complete_request(&mut self, response: lsp_server::Response) {
let handler = self
.req_queue
.outgoing
.complete(response.id.clone())
.expect("received response for unknown request");
handler(self, response)
}
pub(crate) fn send_notification<N: lsp_types::Notification>(&self, params: N::Params) {
let not = lsp_server::Notification::new(N::METHOD.into(), params);
self.send(not.into());
}
pub(crate) fn register_request(
&mut self,
request: &lsp_server::Request,
request_received: Instant,
) {
self.req_queue
.incoming
.register(request.id.clone(), (request.method.clone(), request_received));
}
View on GitHub (pinned to e8f7e90aa3)
Solutions
- Inspect the client: find what request id it is responding with and why it does not match any outgoing request (enable LSP trace logging of request/response ids).
- Update the LSP client/extension to a version that correctly tracks server-issued request ids.
- If a proxy or wrapper sits between client and server, ensure it forwards responses verbatim without duplicating or re-numbering ids.
- As a workaround, restart the language server to reset the request queue; report the client bug upstream if reproducible.
Example fix
// client-side before: replying with a guessed id
send({ id: 0, result: null });
// after: echo the id from the server's request message
send({ id: serverRequest.id, result: computeResult(serverRequest.method) }); Defensive patterns
Strategy: validation
Validate before calling
// client side: before replying, confirm the id is one you actually received from the server
if (!pendingServerRequests.has(response.id)) {
console.warn('ignoring response for unknown request', response.id);
return;
}
pendingServerRequests.delete(response.id); Type guard
function hasPendingRequest(id: string | number): boolean {
return pendingServerRequests.has(id);
} Prevention
- Always echo the exact id from the server's request when responding.
- Never send duplicate responses for one request id.
- Buffer only responses within a single server session; drop them across restarts.
- Enable LSP trace logs to verify id pairing during client development.
When it happens
Trigger: A buggy language client sends a response with an id rust-analyzer never issued, sends a duplicate response for the same id (already completed via complete()), or sends a response after the request was handled/cleaned up during a restart or server reload.
Common situations: Custom or third-party LSP client implementations, clients that replay buffered responses after a server restart, middleware/proxies that duplicate or re-id messages, and client extensions responding to window/workDoneProgress or apply edits with stale ids.
Related errors
- client exited without proper shutdown sequence
- we never provide completions for excluded files
- we never provide code actions for excluded files
- unable to get FileId
- Unable to get AbsPath
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/086d50f96f385bd1.
Report an issue: GitHub.