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

  1. 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).
  2. Update the LSP client/extension to a version that correctly tracks server-issued request ids.
  3. If a proxy or wrapper sits between client and server, ensure it forwards responses verbatim without duplicating or re-numbering ids.
  4. 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

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


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/086d50f96f385bd1. Report an issue: GitHub.