rust-lang/rust · critical · anyhow::Error

A receiver has been dropped, something panicked!

Error message

A receiver has been dropped, something panicked!

What it means

Returned at the end of the main event loop when next_event returns an error (the crossbeam/lsp_server Receiver was dropped rather than yielding a message). In r-a's design the receiver is held by scheduler threads; a drop indicates one of them panicked, so the loop cannot continue and reports it.

Source

Thrown at src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs:217

                self.fetch_workspaces(cause, path, force_crate_graph_reload);
            }
        }

        while let Ok(event) = self.next_event(&inbox) {
            let Some(event) = event else {
                anyhow::bail!("client exited without proper shutdown sequence");
            };
            if matches!(
                &event,
                Event::Lsp(lsp_server::Message::Notification(Notification { method, .. }))
                if method == lsp_types::ExitNotification::METHOD.as_str()
            ) {
                return Ok(());
            }
            self.handle_event(event);
        }

        Err(anyhow::anyhow!("A receiver has been dropped, something panicked!"))
    }

    fn register_did_save_capability(&mut self, additional_patterns: impl Iterator<Item = String>) {
        let additional_filters = additional_patterns.map(|pattern| {
            lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
                lsp_types::TextDocumentFilterPattern {
                    language: None,
                    scheme: None,
                    pattern: pattern.into(),
                },
            ))
        });

        let mut selectors = vec![
            lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
                lsp_types::TextDocumentFilterPattern {
                    language: None,
                    scheme: None,

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Look earlier in the log for the panic backtrace — that is the real defect; this message is the symptom.
  2. File a rust-analyzer issue with the backtrace and the code that triggered it (r-a must not panic on user code).
  3. Update to a newer rust-analyzer; the panic may already be fixed.
  4. As a workaround, narrow the workspace or disable the feature implicated by the backtrace.

Example fix

// before: opaque message at loop end
Err(anyhow::anyhow!("A receiver has been dropped, something panicked!"))

// after: capture and forward the last recorded panic so users see the cause
let last_panic = std::panic::take_hook(); // or store last panic in a Mutex on hook install
Err(anyhow::anyhow!(
    "A receiver has been dropped, something panicked! \
     Last panic: {}",
    GLOBAL_LAST_PANIC.lock().unwrap().as_deref().unwrap_or("(no backtrace captured)")
))
Defensive patterns

Strategy: try-catch

Validate before calling

// Not preventable by callers — but you can install a panic hook to capture the
// cause so this terminal error is diagnosable:
std::panic::set_hook(Box::new(|info| {
    *GLOBAL_LAST_PANIC.lock().unwrap() =
        Some(format!("{info}"));
}));

Type guard

null

Try / catch

// Catch Anywhere in tasks and convert to a logged error instead of letting the
// sender drop silently:
std::panic::catch_unwind(|| task()).map_err(|p| {
    tracing::error!("task panicked: {p:?}");
})?;

Prevention

When it happens

Trigger: Any panic inside a rust-analyzer task thread that owns the sending side of the event channel — the sender is dropped on unwind, and the main loop's recv() returns Err. Often paired with a panic backtrace earlier in the log.

Common situations: A bug in an analysis pass that panics (which r-a's invariants say must not happen); an unwrap on None in a proc-macro or hir path; OOM abort; a stdx::assert failure unwinding.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/f723f5f9d9816ee5. Report an issue: GitHub.