astral-sh/ruff · error · Error
-32603
-32603
Error message
request handler {error} What it means
ty's LSP server wraps any request handler that panics (caught via `ruff_db::panic::catch_unwind`) into an LSP InternalError (-32603) response with the message `request handler {error}`, where `{error}` is the `PanicError` payload of the panic. It is a catch-all for bugs inside ty's request handlers rather than an error the caller caused. The panic detail and the client's `log_guidance` string are appended so the user knows where to report it.
Solutions
- Capture the full panic message from the LSP log and the code that triggered it, and file a bug at https://github.com/astral-sh/ruff/issues (ty expects panics to be reported as bugs, not handled)
- Restart/reload the language-server session; the salsa database can be left in a bad state after a panic
- Try the latest ty version - the panic may already be fixed
- If the panic blocks a single file, exclude that file from analysis (e.g. via lint config/ignore) as a temporary workaround
Example fix
// A handler that panics on missing data
// before
let module = db.module(module_name).unwrap();
// after
let Some(module) = db.module(module_name) else {
return Err(anyhow!("module {module_name} not found"));
}; Defensive patterns
Strategy: try-catch
Try / catch
// Client-side: handle an InternalError (-32603) response
match response {
Ok(result) => use(result),
Err(err) if err.code == -32603 => {
log::error!("ty request handler panicked: {} - please report this bug", err.message);
restart_language_server();
None // degrade gracefully
}
Err(err) => return Err(err),
} Prevention
- Keep ty updated to the latest release so known handler panics are fixed
- If a panic reproduces on a specific file, minimize it and file an issue with the repro
- Avoid relying on the server after a panic response - restart the session before continuing
- Watch the LSP logs for `request handler` messages to catch regressions early
When it happens
Trigger: Any LSP request (hover, completion, code action, document diagnostics, etc.) whose handler panics - e.g. a salsa query panics, an unwrap/expect fails, or an index-out-of-bounds occurs inside `R::handle_request` - and the panic is not a `salsa::Cancelled` cancellation (cancellations are retried or reported as ContentModified instead).
Common situations: A genuine ty bug triggered by unusual Python source (syntax edge cases, exotic type constructs); editing many documents rapidly such that salsa invalidation races surface latent panics; running an in-development ty version against a codebase pattern the handler never expected.
Related errors
- InternalError
- InternalError
- accumulator should not be empty
- anchor should not be NodeIndex::NONE
- argument index should be valid
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/91afa36fbcc5427f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/ty_server/src/server/api.rs:402
tracing::debug!(
"request id={} method={} was cancelled by salsa, re-queueing for retry",
request.id,
request.method
);
client.retry(request);
} else {
tracing::debug!(
"request id={} was cancelled by salsa, sending content modified",
id
);
respond_silent_error(id.clone(), client, R::salsa_cancellation_error());
}
} else {
respond::<R>(
id,
Err(Error {
code: lsp_server::ErrorCode::InternalError,
error: anyhow!("request handler {error}"),
}),
client,
log_guidance,
);
}
}
fn sync_notification_task<N: traits::SyncNotificationHandler>(
notif: server::Notification,
) -> Result<Task> {
let (id, params) = cast_notification::<N>(notif)?;
Ok(Task::sync(move |session, client| {
let _span = tracing::debug_span!("notification", method = %N::METHOD).entered();
if let Err(err) = N::run(session, client, params) {
tracing::error!("An error occurred while running {id}: {err}");
client.show_error_message(format!(
"ty encountered a problem. {}",
session.client_name().log_guidance()View on GitHub (pinned to 26f38c119c)