zellij-org/zellij · error · anyhow::Error
cannot respawn plugin panes
Error message
cannot respawn plugin panes
What it means
PtyBus::rerun_command_in_pane matches on PaneId: the Terminal arm spawns a fresh command, while the catch-all arm (PaneId::Plugin) immediately returns this error. Only terminal panes hold a PTY child process that can be re-run; plugin panes have no command to respawn.
Source
Thrown at zellij-server/src/pty.rs:1943
self.task_handles.insert(id, terminal_bytes);
self.pane_activity_flags.insert(id, activity_flag);
if let Some(child_pid) = child_pid {
self.id_to_child_pid.insert(id, child_pid);
self.capture_initial_cwd(id, child_pid);
}
if let Some(originating_plugin) = self.originating_plugins.get(&id) {
self.bus
.senders
.send_to_plugin(PluginInstruction::Update(vec![(
Some(originating_plugin.plugin_id),
Some(originating_plugin.client_id),
Event::CommandPaneReRun(id, originating_plugin.context.clone()),
)]))
.with_context(err_context)?;
}
Ok(())
},
_ => Err(anyhow!("cannot respawn plugin panes")).with_context(err_context),
}
}
pub fn populate_session_layout_metadata(
&mut self,
session_layout_metadata: &mut SessionLayoutMetadata,
) {
let terminal_ids = session_layout_metadata.all_terminal_ids();
let mut terminal_ids_to_commands: HashMap<u32, Vec<String>> = HashMap::new();
let mut terminal_ids_to_cwds: HashMap<u32, PathBuf> = HashMap::new();
let pids: Vec<_> = terminal_ids
.iter()
.filter_map(|id| self.id_to_child_pid.get(&id))
.copied()
.collect();
let (pids_to_cwds, pids_to_cmds) = self
.bus
.os_inputView on GitHub (pinned to 98a0837077)
Solutions
- Check that the pane you target is a terminal pane, not a plugin pane (pane ids carry an is_plugin flag in the plugin API)
- To 'refresh' a plugin pane, use the plugin reload action (start_or_reload_plugin) instead of a command re-run
- If developing zellij, return a clearer message naming the PaneId::Plugin case in the catch-all arm
Example fix
// before (plugin pseudocode)
rerun_command_in_pane(pane_id); // pane_id may be a plugin pane -> Err
// after (plugin pseudocode)
if !pane_id.is_plugin {
rerun_command_in_pane(pane_id);
} else {
start_or_reload_plugin(&env, &plugin_url);
} Defensive patterns
Strategy: type-guard
Type guard
fn rerunnable(pane_id: PaneId) -> bool {
matches!(pane_id, PaneId::Terminal(_))
} Try / catch
match pane_id {
PaneId::Terminal(id) => pty.rerun_command_in_pane(pane_id, cmd),
PaneId::Plugin(_) => Err(anyhow!("cannot respawn plugin panes")).with_context(err_context),
} Prevention
- Check the pane's is_plugin flag before issuing re-run actions
- Use plugin reload actions for plugin panes
When it happens
Trigger: An Action that re-runs a pane command (e.g. the 'run command again' / CommandPaneReRun flow) is dispatched with a PaneId::Plugin instead of PaneId::Terminal — usually a caller passing the wrong pane id type or a plugin pane id where a terminal id was expected.
Common situations: Plugin code capturing a pane id from an event and feeding it to a re-run/respawn action without checking whether the pane is a terminal; keybindings or sessions scripts that reference a plugin pane's id.
Related errors
- Worker name not specified in message to worker
- Worker name ("{}") should not be specified in message to plu
- Plugin is not stored in memory
- Failed to serialize user configuration: {:?}
- Failed to get running plugin
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/d828a15fc1341257.
Report an issue: GitHub.