zellij-org/zellij · error · anyhow::Error

Failed to deserialize layout: {}

Error message

Failed to deserialize layout: {}

What it means

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.

Source

Thrown at zellij-server/src/plugins/zellij_exports.rs:2965

    let error_msg = || format!("Failed to detach");
    apply_action!(action, error_msg, env);
}

fn switch_session(
    env: &PluginEnv,
    session_name: Option<String>,
    tab_position: Option<usize>,
    pane_id: Option<(u32, bool)>,
    layout: Option<LayoutInfo>,
    cwd: Option<PathBuf>,
) -> Result<()> {
    // pane_id is (id, is_plugin)
    let err_context = || format!("Failed to switch session");
    if let Some(LayoutInfo::Stringified(stringified_layout)) = layout.as_ref() {
        // we verify the stringified layout here to fail early rather than when parsing it at the
        // session-switching phase
        if let Err(e) = Layout::from_kdl(&stringified_layout, None, None, None) {
            return Err(anyhow!("Failed to deserialize layout: {}", e));
        }
    }

    let (completion_tx, completion_rx) = oneshot::channel();

    if session_name
        .as_ref()
        .map(|s| s.contains('/'))
        .unwrap_or(false)
    {
        log::error!("Session names cannot contain \'/\'");
    } else {
        let client_id = env.client_id;
        let tab_position = tab_position.map(|p| p + 1); // ¯\_()_/¯
        let cwd = cwd
            .map(|c| translate_plugin_path(env, c))
            .or_else(|| Some(env.plugin_cwd.clone()));
        let connect_to_session = ConnectToSession {

View on GitHub (pinned to 98a0837077)

Solutions

  1. Run `zellij setup --check` on the same layout content to see the precise KDL error
  2. Re-serialize the layout with the current zellij version (dump it fresh via the dump-layout API) rather than reusing an old blob
  3. If sessions were saved by an older zellij, migrate/re-dump them before switching
  4. Handle the Err return in the plugin and surface the message to the user instead of retrying the switch
Defensive patterns

Strategy: validation

Validate before calling

// plugin-side: pre-validate stringified layouts before switching sessions
if let Some(LayoutInfo::Stringified(s)) = layout.as_ref() {
    if kdl_parse_fails(s) { return Err(anyhow!("layout blob no longer valid; re-dump it")); }
}

Try / catch

match Layout::from_kdl(&stringified_layout, None, None, None) {
    Ok(_) => proceed_with_switch(),
    Err(e) => Err(anyhow!("Failed to deserialize layout: {e}")),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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