zellij-org/zellij · error

Unspecified bare key

Error message

Unspecified bare key

What it means

Thrown by TryFrom<ProtoBareKey> for BareKey when the proto enum holds its default/placeholder value Unspecified. In proto3 an unset enum serializes as 0, which maps to Unspecified, so this means the sender never set bare_key (or explicitly sent the placeholder) on a KeyWithModifier message.

Source

Thrown at zellij-utils/src/ipc/enum_conversions.rs:89

            ProtoBareKey::F5 => Ok(BareKey::F(5)),
            ProtoBareKey::F6 => Ok(BareKey::F(6)),
            ProtoBareKey::F7 => Ok(BareKey::F(7)),
            ProtoBareKey::F8 => Ok(BareKey::F(8)),
            ProtoBareKey::F9 => Ok(BareKey::F(9)),
            ProtoBareKey::F10 => Ok(BareKey::F(10)),
            ProtoBareKey::F11 => Ok(BareKey::F(11)),
            ProtoBareKey::F12 => Ok(BareKey::F(12)),
            ProtoBareKey::Char => Err(anyhow!("Character key needs character data")),
            ProtoBareKey::Tab => Ok(BareKey::Tab),
            ProtoBareKey::Esc => Ok(BareKey::Esc),
            ProtoBareKey::Enter => Ok(BareKey::Enter),
            ProtoBareKey::CapsLock => Ok(BareKey::CapsLock),
            ProtoBareKey::ScrollLock => Ok(BareKey::ScrollLock),
            ProtoBareKey::NumLock => Ok(BareKey::NumLock),
            ProtoBareKey::PrintScreen => Ok(BareKey::PrintScreen),
            ProtoBareKey::Pause => Ok(BareKey::Pause),
            ProtoBareKey::Menu => Ok(BareKey::Menu),
            ProtoBareKey::Unspecified => Err(anyhow!("Unspecified bare key")),
        }
    }
}

// KeyModifier conversions
impl From<KeyModifier> for ProtoKeyModifier {
    fn from(modifier: KeyModifier) -> Self {
        match modifier {
            KeyModifier::Ctrl => ProtoKeyModifier::Ctrl,
            KeyModifier::Alt => ProtoKeyModifier::Alt,
            KeyModifier::Shift => ProtoKeyModifier::Shift,
            KeyModifier::Super => ProtoKeyModifier::Super,
        }
    }
}

impl TryFrom<ProtoKeyModifier> for KeyModifier {
    type Error = anyhow::Error;

View on GitHub (pinned to bf8d23a4f7)

Solutions

  1. Set an explicit non-Char, non-Unspecified bare_key on every key message you send (Char additionally needs the character field).
  2. Validate inbound frames at your boundary: reject bare_key == Unspecified (i32 0) before conversion.
  3. If receiving this from zellij itself, check for client/server version mismatch and align versions.

Example fix

// before: default proto leaves the enum unset
let msg = KeyWithModifier { key_modifiers: vec![Ctrl as i32], ..Default::default() };
let key: KeyWithModifier = msg.try_into()?; // Err("Unspecified bare key")

// after: set the discriminant explicitly
let msg = KeyWithModifier { bare_key: BareKey::Enter as i32, key_modifiers: vec![Ctrl as i32], character: None };
let key: KeyWithModifier = msg.try_into()?;
Defensive patterns

Strategy: type-guard

Validate before calling

// reject frames whose bare_key was never set
if msg.bare_key == ProtoBareKey::Unspecified as i32 { // covers i32 0
    return Ok(None); // ignore malformed frame
}

Type guard

fn has_bare_key(k: &ProtoKeyWithModifier) -> bool {
    ProtoBareKey::from_i32(k.bare_key)
        .map(|key| key != ProtoBareKey::Unspecified)
        .unwrap_or(false)
}

Try / catch

match bare_key_from_proto_i32(msg.bare_key) {
    Ok(key) => Some(key),
    Err(e) if e.to_string() == "Unspecified bare key" => {
        log::debug!("ignoring key frame with unset bare_key");
        None
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Constructing or receiving a key message with bare_key left at default — e.g. handcrafted IPC frames, a client library that only sets modifiers, or a defaulted/empty message passed through bare_key_from_proto_i32 (which succeeds at from_i32(0) then fails at try_into).

Common situations: First drafts of custom zellij clients/web clients; test fixtures built with struct-default field values; version skew where a newer message shape stops filling the field.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of zellij-org/zellij@bf8d23a4f7 (2026-08-19). Data as JSON: /api/errors/16c26ad0906d328c. Report an issue: GitHub.