{"record":{"id":"4be406a31d8abc7c","repo":"zellij-org/zellij","slug":"failed-to-parse-layout","errorCode":null,"errorMessage":"Failed to parse layout: {:?}","messagePattern":"Failed to parse layout: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"zellij-server/src/plugins/zellij_exports.rs","lineNumber":2729,"sourceCode":"        .with_context(err_context)?;\n    Ok(())\n}\n\nfn switch_to_mode(env: &PluginEnv, input_mode: InputMode) {\n    let action = Action::SwitchToMode { input_mode };\n    let error_msg = || format!(\"failed to switch to mode in plugin {}\", env.name());\n    apply_action!(action, error_msg, env);\n}\n\nfn new_tabs_with_layout(env: &PluginEnv, raw_layout: &str) -> Result<()> {\n    // TODO: cwd\n    let layout = Layout::from_str(\n        &raw_layout,\n        format!(\"Layout from plugin: {}\", env.name()),\n        None,\n        None,\n    )\n    .map_err(|e| anyhow!(\"Failed to parse layout: {:?}\", e))?;\n    apply_layout(env, layout);\n    Ok(())\n}\n\nfn new_tabs_with_layout_info(env: &PluginEnv, layout_info: LayoutInfo) -> Result<()> {\n    // TODO: cwd\n    let layout = Layout::from_layout_info(&env.layout_dir, layout_info)\n        .map_err(|e| anyhow!(\"Failed to parse layout: {:?}\", e))?;\n    apply_layout(env, layout);\n    Ok(())\n}\n\nfn apply_layout(env: &PluginEnv, layout: Layout) {\n    let mut tabs_to_open = vec![];\n    let tabs = layout.tabs();\n    let cwd = None; // TODO: add this to the plugin API\n    if tabs.is_empty() {\n        let swap_tiled_layouts = Some(layout.swap_tiled_layouts.clone());","sourceCodeStart":2711,"sourceCodeEnd":2747,"githubUrl":"https://github.com/zellij-org/zellij/blob/98a0837077492d53dd252ab30bc3e43e41e504f4/zellij-server/src/plugins/zellij_exports.rs#L2711-L2747","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"// before (plugin)\nnew_tabs_with_layout(&format!(\"layout {{ pane split_direction=\\\"{dir}\\\" }}\")); // dir may be invalid\n\n// after (plugin)\nassert!([\"left\",\"right\"].contains(&dir.as_str()));\nnew_tabs_with_layout(&format!(\"layout {{ pane split_direction=\\\"{dir}\\\" }}\"));","handlingStrategy":"validation","validationCode":"// plugin-side: dry-run the KDL before sending\nfn valid_layout_kdl(s: &str) -> bool {\n    // parse with a KDL parser or reuse a `parse_layout` host call and check for errors\n    !s.is_empty() && s.contains(\"layout\")\n}","typeGuard":null,"tryCatchPattern":"match Layout::from_str(&raw_layout, ctx, None, None) {\n    Ok(layout) => apply_layout(env, layout),\n    Err(e) => log::warn!(\"invalid layout from plugin: {e:?}\"),\n}","preventionTips":["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"],"tags":["layout","kdl","plugin","parsing"],"backgroundTag":null,"analyzedSha":"98a0837077492d53dd252ab30bc3e43e41e504f4","analyzedAt":"2026-08-16T13:02:01.396Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}