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_metadataView on GitHub (pinned to 98a0837077)
Solutions
- Set exactly one oneof arm before sending: layout_type: Some(FilePath(path)), BuiltinName(name), Url(url), or Stringified(content).
- If you built the message with default(), remember optional oneof fields do not default - assign them explicitly.
- Check the receiver supports the variant you send (the converter handles FilePath, Url, and Stringified; verify BuiltinName support on your version).
- 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
- Remember proto3 oneof arms have no default - unset means None and fails here.
- When copying LayoutInfo between messages, copy layout_type and layout_metadata together.
- Set exactly one source arm (FilePath / BuiltinName / Url / Stringified) and verify the receiver supports it on your zellij version.
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
- MovePaneByPaneId missing pane_id
- MovePaneBackwardsByPaneId missing pane_id
- TogglePanePinnedByPaneId missing pane_id
- PageScrollUpByPaneId missing pane_id
- PageScrollDownByPaneId missing pane_id
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/cfba611f1b88e3bb.
Report an issue: GitHub.