Skip to content

fix(rust): answer the request id when a handler panics - #2311

Open
rinceyuan wants to merge 1 commit into
github:mainfrom
rinceyuan:fix/rust-request-handler-panic
Open

fix(rust): answer the request id when a handler panics#2311
rinceyuan wants to merge 1 commit into
github:mainfrom
rinceyuan:fix/rust-request-handler-panic

Conversation

@rinceyuan

Copy link
Copy Markdown
Contributor

Summary

Follow-up items from #2034, tracked in #2053.

1. A panicking request handler left the request unanswered.
Since #2034 each inbound JSON-RPC request is dispatched to its own tokio::spawned task. A panic inside a handler is isolated to that task, so the request id is simply never answered and the caller waits out its own timeout. This catches the unwind at the dispatch boundary and replies with -32603 for that id. The panic payload is not exposed; the method name is logged at error!.

2. Stale lifecycle documentation.
Session::stop_event_loop and the Drop impl still claimed that in-flight handlers complete before the loop exits. That has not been true since request dispatch moved to spawned tasks. The rustdoc now says handlers may outlive the loop and that their response can be lost if the connection closes first. The comment on stop_event_loop_completes_in_flight_handler claimed the loop was parked inside handle_request, which is likewise no longer how the test passes.

Tests

New panicking_request_handler_responds_with_internal_error in session_test:

  • drives a userInput.request into a handler that panics and asserts a -32603 response for that id,
  • then sends a second request and asserts the loop is still serving it, so the panic stays isolated.

Verified it times out (the reported symptom) with the source change reverted.

cargo +nightly-2026-04-14 fmt --check                        # clean
cargo clippy --all-features --all-targets -- -D warnings     # clean
cargo test --all-features --lib                              # 226 passed
cargo test --all-features --test session_test                # 118 passed
cargo test --all-features --test jsonrpc_test --test api_types_test --test protocol_version_test

The e2e target and cli_resolution_test::stale_env_override_falls_through need the bundled CLI, which cannot be downloaded from this machine (TLS interception on registry.npmjs.org), so they were run with COPILOT_SKIP_CLI_DOWNLOAD=1 and fail identically on a clean checkout.

Fixes #2053.

Requests are dispatched to their own spawned tasks, so a panic inside a handler is isolated by tokio and the request is simply never answered - the caller waits out its own timeout. Catch the unwind at the dispatch boundary and reply with a JSON-RPC internal error (-32603) instead; the panic payload is not exposed.

Also corrects the stop_event_loop, Drop and lifecycle-test documentation, which still claimed in-flight handlers complete before the loop exits. That stopped being true when request dispatch moved to spawned tasks.

Fixes github#2053.
@rinceyuan
rinceyuan requested a review from a team as a code owner August 11, 2026 09:36
Copilot AI balanced review requested due to automatic review settings August 11, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds panic recovery at Rust JSON-RPC request dispatch, ensuring callers receive an internal-error response while preserving event-loop isolation.

Changes:

  • Converts handler panics into JSON-RPC -32603 responses.
  • Updates lifecycle documentation for detached handlers.
  • Adds regression coverage for panic recovery and continued request handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
rust/src/session.rs Catches dispatch panics and clarifies shutdown behavior.
rust/tests/session_test.rs Tests panic responses and updates lifecycle commentary.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rust SDK: follow-ups from #2034 — spawned request handlers can outlive stop_event_loop, and a panicking handler leaves the request unanswered

2 participants