astral-sh/ruff · error · anyhow::Error
Failed to send notification
Error message
Failed to send notification (method={method}): {error} What it means
The server sends client notifications (publishDiagnostics, logMessage, ...) by pushing them onto an internal channel read by the main loop, which writes to the actual transport. If that channel is already closed — the main loop has exited because the transport broke or the server is shutting down — the send fails and this error is logged with the method name.
Solutions
- Treat it as expected noise during shutdown: restart the server and verify it reconnects cleanly
- If it recurs mid-session, check the transport (stderr/stdout pipes not blocked or closed early) and for earlier errors in the log that killed the main loop
- Reduce late work by letting in-flight background tasks drain before exiting (graceful shutdown)
- Update the server — shutdown-ordering improvements land regularly
Defensive patterns
Strategy: try-catch
Try / catch
// Rust: a failed notification send during teardown is not fatal
if let Err(e) = client.send_notification::<lsp_types::notification::PublishDiagnostics>(params) {
tracing::warn!(%e, "dropping notification; main loop likely exited");
} Prevention
- Treat send failures after the main loop exits as expected shutdown noise
- Drain or cancel background tasks before dropping the main loop
- Keep the transport healthy (dedicated stdout for LSP, logs to stderr) so the loop does not die early
When it happens
Trigger: A background task (e.g., a queued lint run) finishing after the client disconnected and the main loop exited; races during shutdown where diagnostics publishing overlaps server teardown; transport errors (broken pipe on stderr/stdout) killing the main loop first.
Common situations: Editor crashes or force-closes while background lint/format tasks are in flight; aggressive process supervision restarting the server; noisy logs during teardown that look like real failures.
Related errors
- Failed to send response for request
- client exited without proper shutdown sequence
- InternalError
- InternalError
- InternalError
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/3d278e56fdc21594.
Report an issue: GitHub.
Appendix: source
Thrown at crates/ruff_server/src/session/client.rs:106
format!("Failed to send request method={method}", method = R::METHOD)
})?;
Ok(())
}
/// Sends a notification to the client.
pub(crate) fn send_notification<N>(&self, params: N::Params) -> crate::Result<()>
where
N: lsp_types::Notification,
{
let method = N::METHOD.to_string();
self.client_sender
.send(lsp_server::Message::Notification(Notification::new(
method, params,
)))
.map_err(|error| {
anyhow!(
"Failed to send notification (method={method}): {error}",
method = N::METHOD
)
})
}
/// Sends a notification without any parameters to the client.
///
/// This is useful for notifications that don't require any data.
#[expect(dead_code)]
fn send_notification_no_params(&self, method: &str) -> crate::Result<()> {
self.client_sender
.send(lsp_server::Message::Notification(Notification::new(
method.to_string(),
Value::Null,
)))
.map_err(|error| anyhow!("Failed to send notification (method={method}): {error}"))
}View on GitHub (pinned to d1087a4b9e)