For me this is a panic that started occurring today in my use of Zed.
The repro is to type `ctrl-x` to start a pending key sequence and then
close the collab side panel with the mouse. The issue is that
dispatching the action based on pending keystrokes uses the same
`DispatchNodeId` as when the 1 second timer was started.
`DispatchNodeId` is not stable across frames. This also means that the
wrong `DispatchNodeId` can be used in the non-panicing case, potentially
causing the action to not occur.
The mystery here is why did this only start happening now in my use of
Zed, and why isn't it showing up in the panics dashboard / issue
reports.
Panic looks like
```
{
"thread": "main",
"payload": "index out of bounds: the len is 467 but the index is 1861",
"location_data": {
"file": "crates/gpui/src/key_dispatch.rs",
"line": 519
},
"backtrace": [
"zed::reliability::init_panic_hook::{{closure}}::he1d8257b19b16eec+155265758",
"std::panicking::rust_panic_with_hook::h33b18b24045abff4+128544307",
"std::panicking::begin_panic_handler::{{closure}}::hf8313cc2fd0126bc+128543530",
"std::sys::backtrace::__rust_end_short_backtrace::h57fe07c8aea5c98a+128537145",
"__rustc[95feac21a9532783]::rust_begin_unwind+128542669",
"core::panicking::panic_fmt::hd54fb667be51beea+9456688",
"core::panicking::panic_bounds_check::h1a9bf3d94de0fc80+9457170",
"gpui::key_dispatch::DispatchTree::dispatch_path::hce77d277881569bf+73992023",
"gpui::app::App::spawn::{{closure}}::hb1e79bbbdead3012+73687056",
"async_task::raw::RawTask<F,T,S,M>::run::hd13f66f99bb24bbd+70694231",
"<gpui::platform::linux::x11::client::X11Client as gpui::platform::linux::platform::LinuxClient>::run::h5a92ddaaf9a06dd1+74465138",
"gpui::platform::linux::platform::<impl gpui::platform::Platform for P>::run::hd19ac52b2d94268e+74064525",
"gpui::app::Application::run::hee83110c717a5af0+151862692",
"zed::main::hca7e2265584c4139+153307630",
"std::sys::backtrace::__rust_begin_short_backtrace::h2e04f4034c2d82c5+153146899",
"std::rt::lang_start::{{closure}}::h91cf1ca0eeae23ae+154454121",
"std::rt::lang_start_internal::h418648f91f5be3a1+128467809",
"main+153326748",
"__libc_start_call_main+25056432783818",
"__libc_start_main_impl+25056432784011",
"_start+12389486"
],
"app_version": "0.190.6",
"app_commit_sha": "9a2dcbbe244407fed51d61f38e4a4a59ec1cccc6",
"release_channel": "stable",
"target": "x86_64-unknown-linux-gnu",
"os_name": "Linux X11",
"os_version": "ubuntu 24.04",
"architecture": "x86_64",
"panicked_on": 1750185799233,
"system_id": "abae7201-61fb-442b-922b-202071ae81c0",
"installation_id": "69a0fb9a-11a2-4065-ad8c-b281e68525ad",
"session_id": "bc5b5f2f-e4c3-44a8-948e-c0550a2e2ef2"
}
```
Release Notes:
- Fixed a rare panic / potential incorrect action dispatch when a
pending keysequence is applied after the 1 second timer elapsing.
@@ -63,6 +63,8 @@ use std::{
rc::Rc,
};
+/// ID of a node within `DispatchTree`. Note that these are **not** stable between frames, and so a
+/// `DispatchNodeId` should only be used with the `DispatchTree` that provided it.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub(crate) struct DispatchNodeId(usize);