{"record":{"id":"51460a45e08d7bdd","repo":"zellij-org/zellij","slug":"unspecified-key-modifier","errorCode":null,"errorMessage":"Unspecified key modifier","messagePattern":"Unspecified key modifier","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"zellij-utils/src/ipc/enum_conversions.rs","lineNumber":115,"sourceCode":"        match modifier {\n            KeyModifier::Ctrl => ProtoKeyModifier::Ctrl,\n            KeyModifier::Alt => ProtoKeyModifier::Alt,\n            KeyModifier::Shift => ProtoKeyModifier::Shift,\n            KeyModifier::Super => ProtoKeyModifier::Super,\n        }\n    }\n}\n\nimpl TryFrom<ProtoKeyModifier> for KeyModifier {\n    type Error = anyhow::Error;\n\n    fn try_from(modifier: ProtoKeyModifier) -> Result<Self> {\n        match modifier {\n            ProtoKeyModifier::Ctrl => Ok(KeyModifier::Ctrl),\n            ProtoKeyModifier::Alt => Ok(KeyModifier::Alt),\n            ProtoKeyModifier::Shift => Ok(KeyModifier::Shift),\n            ProtoKeyModifier::Super => Ok(KeyModifier::Super),\n            ProtoKeyModifier::Unspecified => Err(anyhow!(\"Unspecified key modifier\")),\n        }\n    }\n}\n\n// Helper functions for converting between protobuf i32 and enum types\npub fn bare_key_to_proto_i32(key: BareKey) -> i32 {\n    ProtoBareKey::from(key) as i32\n}\n\npub fn bare_key_from_proto_i32(value: i32) -> Result<BareKey> {\n    let proto_key = ProtoBareKey::try_from(value)\n        .ok()\n        .ok_or_else(|| anyhow!(\"Invalid BareKey value: {}\", value))?;\n    proto_key.try_into()\n}\n\npub fn key_modifier_to_proto_i32(modifier: KeyModifier) -> i32 {\n    ProtoKeyModifier::from(modifier) as i32","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/zellij-org/zellij/blob/bf8d23a4f774abf27a108da2a1a2689e7d8d0d23/zellij-utils/src/ipc/enum_conversions.rs#L97-L133","documentation":"Thrown by TryFrom<ProtoKeyModifier> for KeyModifier when the proto modifier enum equals Unspecified (its proto3 default, i32 0). The reverse conversion (From<KeyModifier>) never produces it, so encountering it means an inbound key_modifiers entry was never actually set by the sender.","triggerScenarios":"A KeyWithModifier's key_modifiers list contains i32 0 (unset/default) — handcrafted frames, defaulted Vec entries, or an intermediate layer that inserts a zero-initialized modifier — and key_modifier_from_proto_i32 / try_into surfaces the error.","commonSituations":"Custom client code pushing placeholder modifier values; protobuf round-trips through code that reconstructs repeated fields with Default::default(); tests with empty modifier entries.","solutions":["Only push real modifier discriminants (Ctrl/Alt/Shift/Super) into key_modifiers; omit the list entirely for no modifiers.","Filter zeros before conversion: retain(|m| *m != 0) on the raw i32 list.","On the zellij side, align client/server versions if well-formed traffic triggers it."],"exampleFix":"// before\nlet msg = KeyWithModifier { bare_key: BareKey::Enter as i32, key_modifiers: vec![0], character: None };\n\n// after: empty list = no modifiers\nlet msg = KeyWithModifier { bare_key: BareKey::Enter as i32, key_modifiers: vec![], character: None };","handlingStrategy":"type-guard","validationCode":"// strip unset (0) modifier entries before conversion\nlet mods: Vec<i32> = msg.key_modifiers.into_iter().filter(|m| *m != 0).collect();","typeGuard":"fn is_valid_modifier(v: i32) -> bool {\n    ProtoKeyModifier::from_i32(v)\n        .map(|m| m != ProtoKeyModifier::Unspecified)\n        .unwrap_or(false)\n}","tryCatchPattern":"match key_modifier_from_proto_i32(m) {\n    Ok(modifier) => Some(modifier),\n    Err(e) if e.to_string() == \"Unspecified key modifier\" => None, // unset entry: skip\n    Err(e) => return Err(e),\n}","preventionTips":["Build key_modifiers lists only from real discriminants; use an empty list for 'no modifiers'.","Filter zero/default i32 values out of repeated enum fields at ingestion.","Unit-test conversion helpers with empty and default-constructed messages."],"tags":["zellij","rust","protobuf","ipc","key-modifiers","default-value"],"backgroundTag":"invalid-enum-value","analyzedSha":"bf8d23a4f774abf27a108da2a1a2689e7d8d0d23","analyzedAt":"2026-08-19T07:42:58.758Z","contentChangedAt":"2026-08-19T07:42:58.758Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}