zellij-org/zellij · error · anyhow::Error
Failed to parse layout: {:?}
Error message
Failed to parse layout: {:?} What it means
new_tabs_with_layout parses a raw KDL layout string supplied by a plugin via Layout::from_str. The map_err wraps the parse failure, so this error means the string the plugin passed is not a valid zellij layout (bad KDL syntax, unknown nodes, invalid pane splits/ratios).
Source
Thrown at zellij-server/src/plugins/zellij_exports.rs:2729
.with_context(err_context)?;
Ok(())
}
fn switch_to_mode(env: &PluginEnv, input_mode: InputMode) {
let action = Action::SwitchToMode { input_mode };
let error_msg = || format!("failed to switch to mode in plugin {}", env.name());
apply_action!(action, error_msg, env);
}
fn new_tabs_with_layout(env: &PluginEnv, raw_layout: &str) -> Result<()> {
// TODO: cwd
let layout = Layout::from_str(
&raw_layout,
format!("Layout from plugin: {}", env.name()),
None,
None,
)
.map_err(|e| anyhow!("Failed to parse layout: {:?}", e))?;
apply_layout(env, layout);
Ok(())
}
fn new_tabs_with_layout_info(env: &PluginEnv, layout_info: LayoutInfo) -> Result<()> {
// TODO: cwd
let layout = Layout::from_layout_info(&env.layout_dir, layout_info)
.map_err(|e| anyhow!("Failed to parse layout: {:?}", e))?;
apply_layout(env, layout);
Ok(())
}
fn apply_layout(env: &PluginEnv, layout: Layout) {
let mut tabs_to_open = vec![];
let tabs = layout.tabs();
let cwd = None; // TODO: add this to the plugin API
if tabs.is_empty() {
let swap_tiled_layouts = Some(layout.swap_tiled_layouts.clone());View on GitHub (pinned to 98a0837077)
Solutions
- Validate the layout string before calling the API — the error payload ({:?}) contains the exact KDL parse error with line/column
- Test the same string with `zellij setup --check` or by loading it as a file layout first
- Escape/interpolate carefully when building the KDL string dynamically in the plugin
- Check layout syntax against the zellij version the plugin targets (layout docs for that release)
Example fix
// before (plugin)
new_tabs_with_layout(&format!("layout {{ pane split_direction=\"{dir}\" }}")); // dir may be invalid
// after (plugin)
assert!(["left","right"].contains(&dir.as_str()));
new_tabs_with_layout(&format!("layout {{ pane split_direction=\"{dir}\" }}")); Defensive patterns
Strategy: validation
Validate before calling
// plugin-side: dry-run the KDL before sending
fn valid_layout_kdl(s: &str) -> bool {
// parse with a KDL parser or reuse a `parse_layout` host call and check for errors
!s.is_empty() && s.contains("layout")
} Try / catch
match Layout::from_str(&raw_layout, ctx, None, None) {
Ok(layout) => apply_layout(env, layout),
Err(e) => log::warn!("invalid layout from plugin: {e:?}"),
} Prevention
- Validate user-supplied layout strings with `zellij setup --check` or a parse-preview API before opening tabs
- Build KDL strings from templates with tested constants, not ad-hoc interpolation
When it happens
Trigger: A plugin calls the new_tabs_with_layout host function with a hand-built or user-provided KDL string containing syntax errors, unknown fields, or invalid values (e.g. non-numeric direction, ratio not summing correctly, missing children).
Common situations: Plugins that let users paste layouts (e.g. session managers, layout pickers) passing unvalidated input; plugin template strings with unescaped braces or interpolation bugs; layouts written for a newer zellij syntax run on an older binary.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to deserialize layout: {}
- Failed to serialize user configuration: {:?}
- failed to load plugin from disk
- Plugin is not stored in memory
- Failed to get running plugin
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/4be406a31d8abc7c.
Report an issue: GitHub.