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

  1. Validate the layout string before calling the API — the error payload ({:?}) contains the exact KDL parse error with line/column
  2. Test the same string with `zellij setup --check` or by loading it as a file layout first
  3. Escape/interpolate carefully when building the KDL string dynamically in the plugin
  4. 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

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

Related errors


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