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

LayoutInfo missing layout_type

Error message

LayoutInfo missing layout_type

What it means

LayoutInfo describes where a layout comes from; its protobuf representation is a oneof layout_type with variants FilePath, BuiltinName, Url, and Stringified, plus an optional layout_metadata. The conversion into data::LayoutInfo matches on the oneof; when layout_type is None (no oneof arm set - legal in proto3), there is no source to build a LayoutInfo from, so it fails with 'LayoutInfo missing layout_type'.

Source

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

    fn try_from(
        layout: crate::client_server_contract::client_server_contract::LayoutInfo,
    ) -> Result<Self> {
        use crate::client_server_contract::client_server_contract::layout_info::LayoutType;
        match layout.layout_type {
            Some(LayoutType::BuiltinName(name)) => Ok(crate::data::LayoutInfo::BuiltIn(name)),
            Some(LayoutType::FilePath(path)) => {
                let layout_metadata = layout
                    .layout_metadata
                    .map(|m| m.try_into())
                    .transpose()?
                    .unwrap_or_default();
                Ok(crate::data::LayoutInfo::File(path, layout_metadata))
            },
            Some(LayoutType::Url(url)) => Ok(crate::data::LayoutInfo::Url(url)),
            Some(LayoutType::Stringified(content)) => {
                Ok(crate::data::LayoutInfo::Stringified(content))
            },
            None => Err(anyhow!("LayoutInfo missing layout_type")),
        }
    }
}

impl From<crate::data::LayoutMetadata> for ProtoLayoutMetadata {
    fn from(metadata: crate::data::LayoutMetadata) -> Self {
        ProtoLayoutMetadata {
            tabs: metadata.tabs.into_iter().map(|t| t.into()).collect(),
            creation_time: metadata.creation_time,
            update_time: metadata.update_time,
        }
    }
}

impl TryFrom<ProtoLayoutMetadata> for crate::data::LayoutMetadata {
    type Error = anyhow::Error;
    fn try_from(proto_metadata: ProtoLayoutMetadata) -> Result<Self> {
        let tabs = proto_metadata

View on GitHub (pinned to 98a0837077)

Solutions

  1. Set exactly one oneof arm before sending: layout_type: Some(FilePath(path)), BuiltinName(name), Url(url), or Stringified(content).
  2. If you built the message with default(), remember optional oneof fields do not default - assign them explicitly.
  3. Check the receiver supports the variant you send (the converter handles FilePath, Url, and Stringified; verify BuiltinName support on your version).
  4. Rebuild senders against the same zellij contract version as the server.

Example fix

// before
let layout_info = LayoutInfo {
    layout_metadata: Some(metadata),
    layout_type: None, // -> "LayoutInfo missing layout_type"
};

// after
let layout_info = LayoutInfo {
    layout_metadata: Some(metadata),
    layout_type: Some(layout_info::LayoutType::Stringified(
        "layout { pane direction="1" }".to_string(),
    )),
};
Defensive patterns

Strategy: validation

Validate before calling

fn layout_info_is_convertible(li: &LayoutInfo) -> bool {
    li.layout_type.is_some()
}

Type guard

fn has_layout_source(li: &LayoutInfo) -> bool {
    matches!(
        li.layout_type,
        Some(layout_info::LayoutType::FilePath(_))
            | Some(layout_info::LayoutType::BuiltinName(_))
            | Some(layout_info::LayoutType::Url(_))
            | Some(layout_info::LayoutType::Stringified(_))
    )
}

Try / catch

match zellij_utils::data::LayoutInfo::try_from(proto_layout_info) {
    Ok(info) => use_layout(info),
    Err(e) if e.to_string().contains("LayoutInfo missing layout_type") => {
        log::warn!("LayoutInfo without a source oneof arm - ignoring");
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Sending a LayoutInfo message where the oneof was never set, e.g. constructing ProtoArrayLayout/LayoutInfo via default() and filling only layout_metadata, or a client that serializes a layout struct without the source field.

Common situations: Plugins or session-management tooling sending resurrect/layout payloads over IPC; version skew where the sender's LayoutInfo lacks the oneof field; code that copies layout_metadata between messages and drops layout_type.

Related errors


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