zellij-org/zellij · error · anyhow::Error
UndoRenamePaneByPaneId missing pane_id
Error message
UndoRenamePaneByPaneId missing pane_id
What it means
UndoRenamePaneByPaneId restores the automatic name of one specific pane after a rename. Note the asymmetry in the conversion: RenamePaneByPaneId accepts an optional pane_id (Option<PaneId> internally), but UndoRenamePaneByPaneId requires it. Its protobuf message UndoRenamePaneByPaneIdAction has one optional pane_id; if None, conversion fails with 'UndoRenamePaneByPaneId missing pane_id'.
Source
Thrown at zellij-utils/src/ipc/protobuf_conversion.rs:3071
ActionType::CloseFocusByPaneId(a) => {
Ok(crate::input::actions::Action::CloseFocusByPaneId {
pane_id: a
.pane_id
.ok_or_else(|| anyhow!("CloseFocusByPaneId missing pane_id"))?
.try_into()?,
})
},
ActionType::RenamePaneByPaneId(a) => {
Ok(crate::input::actions::Action::RenamePaneByPaneId {
pane_id: a.pane_id.map(|p| p.try_into()).transpose()?,
name: a.name,
})
},
ActionType::UndoRenamePaneByPaneId(a) => {
Ok(crate::input::actions::Action::UndoRenamePaneByPaneId {
pane_id: a
.pane_id
.ok_or_else(|| anyhow!("UndoRenamePaneByPaneId missing pane_id"))?
.try_into()?,
})
},
ActionType::TogglePanePinnedByPaneId(a) => {
Ok(crate::input::actions::Action::TogglePanePinnedByPaneId {
pane_id: a
.pane_id
.ok_or_else(|| anyhow!("TogglePanePinnedByPaneId missing pane_id"))?
.try_into()?,
})
},
ActionType::FocusPaneByPaneId(a) => {
Ok(crate::input::actions::Action::FocusPaneByPaneId {
pane_id: a
.pane_id
.ok_or_else(|| anyhow!("FocusPaneByPaneId missing pane_id"))?
.try_into()?,
})View on GitHub (pinned to 98a0837077)
Solutions
- Set pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(id)) }) - undo requires a concrete pane.
- Use the plain UndoRenamePane action for the focused pane.
- If the pane lookup returns None, skip the undo instead of sending an incomplete message.
- Pin client, server, and plugins to the same zellij version.
Example fix
// before
let action = ActionType::UndoRenamePaneByPaneId(
UndoRenamePaneByPaneIdAction { pane_id: None },
); // -> "UndoRenamePaneByPaneId missing pane_id"
// after
let action = ActionType::UndoRenamePaneByPaneId(
UndoRenamePaneByPaneIdAction {
pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(1)) }),
},
); Defensive patterns
Strategy: validation
Validate before calling
fn is_sendable(a: &UndoRenamePaneByPaneIdAction) -> bool {
a.pane_id
.as_ref()
.and_then(|p| p.pane_type.as_ref())
.is_some()
} Type guard
fn has_valid_pane_id(a: &UndoRenamePaneByPaneIdAction) -> bool {
matches!(
a.pane_id.as_ref().and_then(|p| p.pane_type.as_ref()),
Some(pane_id::PaneType::Terminal(_)) | Some(pane_id::PaneType::Plugin(_))
)
} Try / catch
match Action::try_from(proto_action) {
Ok(action) => dispatch(action),
Err(e) if e.to_string().contains("UndoRenamePaneByPaneId missing pane_id") => {
log::warn!("undo-rename without pane target: {e}");
},
Err(e) => return Err(e),
} Prevention
- Rename accepts an optional pane_id but Undo requires one - do not mirror their builders.
- Carry the pane id used for Rename into the later Undo call.
- Document per-variant required fields in your action-sending wrapper.
When it happens
Trigger: Sending ActionType::UndoRenamePaneByPaneId with UndoRenamePaneByPaneIdAction.pane_id = None, e.g. mirroring the optional-pane_id pattern used for RenamePaneByPaneId.
Common situations: Plugins implementing rename/undo-rename pairs and assuming both accept optional pane ids; default prost construction; version skew; intending the focused-pane UndoRenamePane variant.
Related errors
- PageScrollUpByPaneId missing pane_id
- PageScrollDownByPaneId missing pane_id
- HalfPageScrollUpByPaneId missing pane_id
- HalfPageScrollDownByPaneId missing pane_id
- ResizeByPaneId missing resize_action
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/0e9a82423e441a53.
Report an issue: GitHub.