{"record":{"id":"2c96861034841a82","repo":"zellij-org/zellij","slug":"failed-to-deserialize-layout","errorCode":null,"errorMessage":"Failed to deserialize layout: {}","messagePattern":"Failed to deserialize layout: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"zellij-server/src/plugins/zellij_exports.rs","lineNumber":2965,"sourceCode":"    let error_msg = || format!(\"Failed to detach\");\n    apply_action!(action, error_msg, env);\n}\n\nfn switch_session(\n    env: &PluginEnv,\n    session_name: Option<String>,\n    tab_position: Option<usize>,\n    pane_id: Option<(u32, bool)>,\n    layout: Option<LayoutInfo>,\n    cwd: Option<PathBuf>,\n) -> Result<()> {\n    // pane_id is (id, is_plugin)\n    let err_context = || format!(\"Failed to switch session\");\n    if let Some(LayoutInfo::Stringified(stringified_layout)) = layout.as_ref() {\n        // we verify the stringified layout here to fail early rather than when parsing it at the\n        // session-switching phase\n        if let Err(e) = Layout::from_kdl(&stringified_layout, None, None, None) {\n            return Err(anyhow!(\"Failed to deserialize layout: {}\", e));\n        }\n    }\n\n    let (completion_tx, completion_rx) = oneshot::channel();\n\n    if session_name\n        .as_ref()\n        .map(|s| s.contains('/'))\n        .unwrap_or(false)\n    {\n        log::error!(\"Session names cannot contain \\'/\\'\");\n    } else {\n        let client_id = env.client_id;\n        let tab_position = tab_position.map(|p| p + 1); // ¯\\_()_/¯\n        let cwd = cwd\n            .map(|c| translate_plugin_path(env, c))\n            .or_else(|| Some(env.plugin_cwd.clone()));\n        let connect_to_session = ConnectToSession {","sourceCodeStart":2947,"sourceCodeEnd":2983,"githubUrl":"https://github.com/zellij-org/zellij/blob/98a0837077492d53dd252ab30bc3e43e41e504f4/zellij-server/src/plugins/zellij_exports.rs#L2947-L2983","documentation":"In the switch-session host function, a stringified layout arriving from the plugin is pre-validated with Layout::from_kdl before the session switch proceeds; this error aborts the switch when that KDL fails to parse. The early check exists so the failure surfaces now instead of mid-session-switch.","triggerScenarios":"A plugin calls switch_session with LayoutInfo::Stringified containing KDL that zellij rejects (syntax error, unknown node, invalid values); or a session-layout blob captured by a different zellij version with incompatible syntax.","commonSituations":"Session-manager plugins switching to recorded sessions after a zellij upgrade changed layout syntax; hand-edited serialized session layouts; truncation/corruption of the stringified blob in plugin storage.","solutions":["Run `zellij setup --check` on the same layout content to see the precise KDL error","Re-serialize the layout with the current zellij version (dump it fresh via the dump-layout API) rather than reusing an old blob","If sessions were saved by an older zellij, migrate/re-dump them before switching","Handle the Err return in the plugin and surface the message to the user instead of retrying the switch"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// plugin-side: pre-validate stringified layouts before switching sessions\nif let Some(LayoutInfo::Stringified(s)) = layout.as_ref() {\n    if kdl_parse_fails(s) { return Err(anyhow!(\"layout blob no longer valid; re-dump it\")); }\n}","typeGuard":null,"tryCatchPattern":"match Layout::from_kdl(&stringified_layout, None, None, None) {\n    Ok(_) => proceed_with_switch(),\n    Err(e) => Err(anyhow!(\"Failed to deserialize layout: {e}\")),\n}","preventionTips":["Re-dump serialized layouts after every zellij upgrade instead of persisting blobs indefinitely","Store layouts as files and re-read them at switch time rather than caching stringified copies"],"tags":["layout","kdl","session","plugin","parsing"],"backgroundTag":null,"analyzedSha":"98a0837077492d53dd252ab30bc3e43e41e504f4","analyzedAt":"2026-08-16T13:02:01.396Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}