zellij-org/zellij · error · anyhow::Error

PageScrollDownByPaneId missing pane_id

Error message

PageScrollDownByPaneId missing pane_id

What it means

Zellij converts incoming protobuf IPC actions into its internal Action enum via TryFrom. The PageScrollDownByPaneId variant pages down the scrollback of one specific pane, so the protobuf message PageScrollDownByPaneIdAction must carry the optional field pane_id (a PaneId oneof: Terminal(u32) or Plugin(u32)). If the variant is selected but pane_id is None, conversion fails with 'PageScrollDownByPaneId missing pane_id' and the action never executes.

Source

Thrown at zellij-utils/src/ipc/protobuf_conversion.rs:2954

                    pane_id: a
                        .pane_id
                        .ok_or_else(|| anyhow!("ScrollToBottomByPaneId missing pane_id"))?
                        .try_into()?,
                })
            },
            ActionType::PageScrollUpByPaneId(a) => {
                Ok(crate::input::actions::Action::PageScrollUpByPaneId {
                    pane_id: a
                        .pane_id
                        .ok_or_else(|| anyhow!("PageScrollUpByPaneId missing pane_id"))?
                        .try_into()?,
                })
            },
            ActionType::PageScrollDownByPaneId(a) => {
                Ok(crate::input::actions::Action::PageScrollDownByPaneId {
                    pane_id: a
                        .pane_id
                        .ok_or_else(|| anyhow!("PageScrollDownByPaneId missing pane_id"))?
                        .try_into()?,
                })
            },
            ActionType::HalfPageScrollUpByPaneId(a) => {
                Ok(crate::input::actions::Action::HalfPageScrollUpByPaneId {
                    pane_id: a
                        .pane_id
                        .ok_or_else(|| anyhow!("HalfPageScrollUpByPaneId missing pane_id"))?
                        .try_into()?,
                })
            },
            ActionType::HalfPageScrollDownByPaneId(a) => {
                Ok(crate::input::actions::Action::HalfPageScrollDownByPaneId {
                    pane_id: a
                        .pane_id
                        .ok_or_else(|| anyhow!("HalfPageScrollDownByPaneId missing pane_id"))?
                        .try_into()?,
                })

View on GitHub (pinned to 98a0837077)

Solutions

  1. Populate pane_id with Some(PaneId { pane_type: Some(PaneType::Terminal(id)) }) before sending.
  2. Use the plain PageScrollDown variant when targeting the focused pane.
  3. Align client, server, and plugin builds on the same zellij version.
  4. Add an Action -> proto -> Action round-trip test for every variant you send.

Example fix

// before
let action = ActionType::PageScrollDownByPaneId(PageScrollDownByPaneIdAction {
    pane_id: None, // -> "PageScrollDownByPaneId missing pane_id"
});

// after
let action = ActionType::PageScrollDownByPaneId(PageScrollDownByPaneIdAction {
    pane_id: Some(PaneId {
        pane_type: Some(PaneType::Terminal(1)),
    }),
});
Defensive patterns

Strategy: validation

Validate before calling

fn is_sendable(a: &PageScrollDownByPaneIdAction) -> bool {
    a.pane_id
        .as_ref()
        .and_then(|p| p.pane_type.as_ref())
        .is_some()
}

Type guard

fn has_valid_pane_id(a: &PageScrollDownByPaneIdAction) -> 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("PageScrollDownByPaneId missing pane_id") => {
        log::warn!("incomplete scroll action from client: {e}");
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Sending an action message whose action_type is PageScrollDownByPaneId while PageScrollDownByPaneIdAction.pane_id is None - typically a prost struct built with default() or a client that only fills the oneof discriminator and not the payload.

Common situations: Custom clients or plugins assembling Action messages by hand; zellij client/server version mismatch where the sender's schema lacks the pane_id field; confusion with the focused-pane variant PageScrollDown which needs no pane_id.

Related errors


AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16). Data as JSON: /api/errors/4d475f284b9c2032. Report an issue: GitHub.