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

  1. 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)
  2. Restart/reload the language-server session; the salsa database can be left in a bad state after a panic
  3. Try the latest ty version - the panic may already be fixed
  4. 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

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


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)