zellij-org/zellij · error · anyhow::Error
FocusPaneByPaneId missing pane_id
Error message
FocusPaneByPaneId missing pane_id
What it means
FocusPaneByPaneId gives keyboard focus to one specific pane. Its protobuf message FocusPaneByPaneIdAction carries a single optional pane_id which the internal Action requires. A message selecting this variant with pane_id = None fails conversion with 'FocusPaneByPaneId missing pane_id'.
Source
Thrown at zellij-utils/src/ipc/protobuf_conversion.rs:3087
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()?,
})
},
// Tab-targeting CLI-only variants
ActionType::UndoRenameTabByTabId(a) => {
Ok(crate::input::actions::Action::UndoRenameTabByTabId { id: a.id })
},
ActionType::ToggleActiveSyncTabByTabId(a) => {
Ok(crate::input::actions::Action::ToggleActiveSyncTabByTabId { id: a.id })
},
ActionType::ToggleFloatingPanesByTabId(a) => {
Ok(crate::input::actions::Action::ToggleFloatingPanesByTabId { id: a.id })
},
ActionType::PreviousSwapLayoutByTabId(a) => {
Ok(crate::input::actions::Action::PreviousSwapLayoutByTabId { id: a.id })
},
ActionType::NextSwapLayoutByTabId(a) => {
Ok(crate::input::actions::Action::NextSwapLayoutByTabId { id: a.id })View on GitHub (pinned to 98a0837077)
Solutions
- Set pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(id)) }) before sending.
- If you only need to move focus relative to the current pane, use MoveFocus/MoveFocusOrTab instead.
- Check the resolved pane id is Some before building the action.
- Keep all IPC participants on the same zellij release.
Example fix
// before
let action = ActionType::FocusPaneByPaneId(
FocusPaneByPaneIdAction { pane_id: None },
); // -> "FocusPaneByPaneId missing pane_id"
// after
let action = ActionType::FocusPaneByPaneId(
FocusPaneByPaneIdAction {
pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(1)) }),
},
); Defensive patterns
Strategy: validation
Validate before calling
fn is_sendable(a: &FocusPaneByPaneIdAction) -> bool {
a.pane_id
.as_ref()
.and_then(|p| p.pane_type.as_ref())
.is_some()
} Type guard
fn has_valid_pane_id(a: &FocusPaneByPaneIdAction) -> 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("FocusPaneByPaneId missing pane_id") => {
log::warn!("focus action without pane target: {e}");
},
Err(e) => return Err(e),
} Prevention
- For relative navigation use MoveFocus / MoveFocusOrTab instead of FocusPaneByPaneId.
- Cache pane ids from pane-info events and refresh them on layout changes.
- Guard every focus-by-id send with an is_some() check on pane_id.
When it happens
Trigger: Sending ActionType::FocusPaneByPaneId while FocusPaneByPaneIdAction.pane_id is None - typically a client that resolved no pane id or built the struct with defaults.
Common situations: Plugins focusing panes after navigation events; scripts driving zellij over IPC; client/server protobuf version skew; intending a focused-pane navigation action instead.
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/696060906d9a1772.
Report an issue: GitHub.