{"record":{"id":"06d60f48e431ac62","repo":"zellij-org/zellij","slug":"invalid-inputmode-value","errorCode":null,"errorMessage":"Invalid InputMode value: {}","messagePattern":"Invalid InputMode value: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"zellij-utils/src/ipc/protobuf_conversion.rs","lineNumber":3428,"sourceCode":"}\n\nfn proto_i32_to_input_mode(i: i32) -> Result<InputMode> {\n    match ProtoInputMode::from_i32(i) {\n        Some(ProtoInputMode::Normal) => Ok(InputMode::Normal),\n        Some(ProtoInputMode::Locked) => Ok(InputMode::Locked),\n        Some(ProtoInputMode::Resize) => Ok(InputMode::Resize),\n        Some(ProtoInputMode::Pane) => Ok(InputMode::Pane),\n        Some(ProtoInputMode::Tab) => Ok(InputMode::Tab),\n        Some(ProtoInputMode::Scroll) => Ok(InputMode::Scroll),\n        Some(ProtoInputMode::EnterSearch) => Ok(InputMode::EnterSearch),\n        Some(ProtoInputMode::Search) => Ok(InputMode::Search),\n        Some(ProtoInputMode::RenameTab) => Ok(InputMode::RenameTab),\n        Some(ProtoInputMode::RenamePane) => Ok(InputMode::RenamePane),\n        Some(ProtoInputMode::Session) => Ok(InputMode::Session),\n        Some(ProtoInputMode::Move) => Ok(InputMode::Move),\n        Some(ProtoInputMode::Prompt) => Ok(InputMode::Prompt),\n        Some(ProtoInputMode::Tmux) => Ok(InputMode::Tmux),\n        _ => Err(anyhow!(\"Invalid InputMode value: {}\", i)),\n    }\n}\n\n// Additional helper functions for Action conversion\nfn resize_to_proto_i32(resize: crate::data::Resize) -> i32 {\n    use crate::client_server_contract::client_server_contract::ResizeType;\n    match resize {\n        crate::data::Resize::Increase => ResizeType::Increase as i32,\n        crate::data::Resize::Decrease => ResizeType::Decrease as i32,\n    }\n}\n\nfn direction_to_proto_i32(direction: crate::data::Direction) -> i32 {\n    use crate::client_server_contract::client_server_contract::Direction as ProtoDirection;\n    match direction {\n        crate::data::Direction::Left => ProtoDirection::Left as i32,\n        crate::data::Direction::Right => ProtoDirection::Right as i32,\n        crate::data::Direction::Up => ProtoDirection::Up as i32,","sourceCodeStart":3410,"sourceCodeEnd":3446,"githubUrl":"https://github.com/zellij-org/zellij/blob/98a0837077492d53dd252ab30bc3e43e41e504f4/zellij-utils/src/ipc/protobuf_conversion.rs#L3410-L3446","documentation":"Thrown while converting a protobuf InputMode integer back into the native InputMode enum. The match covers every known ProtoInputMode variant and falls through to this error for anything else. It signals an out-of-range or unrecognized enum value, which almost always means data corruption or a version mismatch between the two sides of the IPC contract.","triggerScenarios":"Calling the InputMode TryFrom conversion with an i32 that does not correspond to any ProtoInputMode variant: a newer enum value sent to an older binary, a corrupted message, or a manually constructed payload with an arbitrary integer.","commonSituations":"Mixing zellij client and server of different versions after a new InputMode variant was added; fuzzed or hand-written protobuf payloads; stale compiled contract after regenerating the .proto files.","solutions":["Align client and server to the same zellij build so the enum sets match","Regenerate the protobuf bindings (client_server_contract) after editing the .proto and rebuild both sides","If accepting untrusted input, validate the i32 against the known variant set before converting"],"exampleFix":"// before\nlet mode = InputMode::try_from(proto_mode_i32)?; // may fail on unknown value\n\n// after\nuse crate::client_server_contract::client_server_contract::InputMode as ProtoInputMode;\nfn is_known_input_mode(v: i32) -> bool {\n    matches!(v, x if x == ProtoInputMode::Normal as i32\n        || x == ProtoInputMode::Locked as i32\n        || x == ProtoInputMode::Resize as i32\n        || x == ProtoInputMode::Pane as i32\n        || x == ProtoInputMode::Tab as i32)\n}\nlet mode = if is_known_input_mode(proto_mode_i32) { InputMode::try_from(proto_mode_i32)? } else { InputMode::Normal };","handlingStrategy":"validation","validationCode":"const KNOWN_INPUT_MODES: &[i32] = &[\n    ProtoInputMode::Normal as i32, ProtoInputMode::Locked as i32,\n    ProtoInputMode::Resize as i32, ProtoInputMode::Pane as i32,\n    ProtoInputMode::Tab as i32, ProtoInputMode::Scroll as i32,\n    ProtoInputMode::EnterSearch as i32, ProtoInputMode::Search as i32,\n    ProtoInputMode::RenameTab as i32, ProtoInputMode::RenamePane as i32,\n    ProtoInputMode::Session as i32, ProtoInputMode::Move as i32,\n    ProtoInputMode::Prompt as i32, ProtoInputMode::Tmux as i32,\n];\nfn is_known_input_mode(v: i32) -> bool { KNOWN_INPUT_MODES.contains(&v) }","typeGuard":"fn is_valid_input_mode(v: i32) -> bool {\n    // regenerate this list from the proto enum when the contract changes\n    KNOWN_INPUT_MODES.contains(&v)\n}","tryCatchPattern":"let mode = InputMode::try_from(proto_value)\n    .with_context(|| format!(\"rejected InputMode value {} (version skew?)\", proto_value))?;","preventionTips":["Regenerate protobuf bindings and rebuild all binaries together after .proto changes","Reject unknown enum ints at the trust boundary with a clear version-skew message","Fuzz the IPC decode path in CI to catch unknown-enum cases early"],"tags":["protobuf","ipc","input-mode","enum-decode"],"backgroundTag":null,"analyzedSha":"98a0837077492d53dd252ab30bc3e43e41e504f4","analyzedAt":"2026-08-16T13:02:01.396Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}