{"record":{"id":"50587fdb6f8a3ec7","repo":"zellij-org/zellij","slug":"movepanebypaneid-missing-pane-id","errorCode":null,"errorMessage":"MovePaneByPaneId missing pane_id","messagePattern":"MovePaneByPaneId missing pane_id","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"zellij-utils/src/ipc/protobuf_conversion.rs","lineNumber":2997,"sourceCode":"                let direction = resize_action\n                    .direction\n                    .map(|d| proto_i32_to_direction(d))\n                    .transpose()?;\n                Ok(crate::input::actions::Action::ResizeByPaneId {\n                    pane_id: a\n                        .pane_id\n                        .ok_or_else(|| anyhow!(\"ResizeByPaneId missing pane_id\"))?\n                        .try_into()?,\n                    resize,\n                    direction,\n                })\n            },\n            ActionType::MovePaneByPaneId(a) => {\n                let direction = a.direction.map(|d| proto_i32_to_direction(d)).transpose()?;\n                Ok(crate::input::actions::Action::MovePaneByPaneId {\n                    pane_id: a\n                        .pane_id\n                        .ok_or_else(|| anyhow!(\"MovePaneByPaneId missing pane_id\"))?\n                        .try_into()?,\n                    direction,\n                })\n            },\n            ActionType::MovePaneBackwardsByPaneId(a) => {\n                Ok(crate::input::actions::Action::MovePaneBackwardsByPaneId {\n                    pane_id: a\n                        .pane_id\n                        .ok_or_else(|| anyhow!(\"MovePaneBackwardsByPaneId missing pane_id\"))?\n                        .try_into()?,\n                })\n            },\n            ActionType::ClearScreenByPaneId(a) => {\n                Ok(crate::input::actions::Action::ClearScreenByPaneId {\n                    pane_id: a\n                        .pane_id\n                        .ok_or_else(|| anyhow!(\"ClearScreenByPaneId missing pane_id\"))?\n                        .try_into()?,","sourceCodeStart":2979,"sourceCodeEnd":3015,"githubUrl":"https://github.com/zellij-org/zellij/blob/98a0837077492d53dd252ab30bc3e43e41e504f4/zellij-utils/src/ipc/protobuf_conversion.rs#L2979-L3015","documentation":"MovePaneByPaneId moves one specific pane inside the layout, optionally in a Direction. Its protobuf message MovePaneByPaneIdAction carries optional pane_id and optional direction; direction may legitimately be None (conversion maps it to None), but pane_id is mandatory. If pane_id is None the conversion fails with 'MovePaneByPaneId missing pane_id'.","triggerScenarios":"Sending ActionType::MovePaneByPaneId where MovePaneByPaneIdAction.pane_id is None (with or without direction set).","commonSituations":"Automation moving panes programmatically; plugins hand-assembling move actions; client/server schema version skew; confusing with the focused-pane MovePane variant.","solutions":["Set pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(id)) }); direction stays optional.","Use the plain MovePane variant when moving the focused pane.","Align all IPC participants on the same zellij release.","Add a unit test that converts every action variant you emit to catch missing fields early."],"exampleFix":"// before\nlet action = ActionType::MovePaneByPaneId(MovePaneByPaneIdAction {\n    pane_id: None, // -> \"MovePaneByPaneId missing pane_id\"\n    direction: Some(Direction::Right as i32),\n});\n\n// after\nlet action = ActionType::MovePaneByPaneId(MovePaneByPaneIdAction {\n    pane_id: Some(PaneId { pane_type: Some(PaneType::Terminal(1)) }),\n    direction: Some(Direction::Right as i32),\n});","handlingStrategy":"validation","validationCode":"fn is_sendable(a: &MovePaneByPaneIdAction) -> bool {\n    a.pane_id\n        .as_ref()\n        .and_then(|p| p.pane_type.as_ref())\n        .is_some() // direction is genuinely optional here\n}","typeGuard":"fn has_valid_pane_id(a: &MovePaneByPaneIdAction) -> bool {\n    matches!(\n        a.pane_id.as_ref().and_then(|p| p.pane_type.as_ref()),\n        Some(pane_id::PaneType::Terminal(_)) | Some(pane_id::PaneType::Plugin(_))\n    )\n}","tryCatchPattern":"match Action::try_from(proto_action) {\n    Ok(action) => dispatch(action),\n    Err(e) if e.to_string().contains(\"MovePaneByPaneId missing pane_id\") => {\n        log::warn!(\"move action without pane target: {e}\");\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Only pane_id is required; do not over-validate and reject valid directionless moves.","Resolve pane ids from a pane-info query rather than hardcoding.","Keep a typed list of which action variants require which fields and assert on it in tests."],"tags":["zellij","ipc","protobuf","rust","pane-id","layout"],"backgroundTag":null,"analyzedSha":"98a0837077492d53dd252ab30bc3e43e41e504f4","analyzedAt":"2026-08-16T13:02:01.396Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}