{"record":{"id":"54b9ba474cacd034","repo":"zellij-org/zellij","slug":"process-returned-non-zero-exit-code","errorCode":null,"errorMessage":"Process returned non-zero exit code: {}","messagePattern":"Process returned non-zero exit code: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"zellij-client/src/lib.rs","lineNumber":467,"sourceCode":"/// On Unix the server daemonizes (double-fork) inside start_server(), so\n/// the intermediate child exits immediately and `cmd.status()` returns.\n#[cfg(not(windows))]\npub fn spawn_server(socket_path: &Path, debug: bool) -> io::Result<()> {\n    let mut cmd = Command::new(current_exe()?);\n    cmd.arg(\"--server\").arg(socket_path);\n    if debug {\n        cmd.arg(\"--debug\");\n    }\n    let status = cmd.status()?;\n    if status.success() {\n        Ok(())\n    } else {\n        let msg = \"Process returned non-zero exit code\";\n        let err_msg = match status.code() {\n            Some(c) => format!(\"{}: {}\", msg, c),\n            None => msg.to_string(),\n        };\n        Err(io::Error::new(io::ErrorKind::Other, err_msg))\n    }\n}\n\n/// Spawn the Zellij server process.\n///\n/// On Windows there is no daemonize — we launch the server as a background\n/// process with a hidden console.  We use CREATE_NO_WINDOW (not\n/// DETACHED_PROCESS) so the server gets valid standard handles;\n/// DETACHED_PROCESS leaves stdin/stdout/stderr as NULL, which breaks PTY\n/// creation, WASM plugin loading, and logging.\n#[cfg(windows)]\npub fn spawn_server(socket_path: &Path, debug: bool) -> io::Result<()> {\n    use std::os::windows::process::CommandExt;\n    let mut cmd = Command::new(current_exe()?);\n    cmd.arg(\"--server\").arg(socket_path);\n    if debug {\n        cmd.arg(\"--debug\");\n    }","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/zellij-org/zellij/blob/98a0837077492d53dd252ab30bc3e43e41e504f4/zellij-client/src/lib.rs#L449-L485","documentation":"Returned by spawn_server (Unix) when the freshly spawned `zellij --server <socket>` child process exits with a non-zero status. The parent only relays the exit code, so the real cause lives in the child's own stderr/log output. On Unix the server daemonizes via double-fork, so a non-zero status here means the server failed before or during daemonization.","triggerScenarios":"`zellij --server <socket_path>` exiting non-zero: unwritable/owned-by-another-user socket directory, a stale socket file conflicting with the new session, session name already in use, or a binary/version mismatch after an upgrade.","commonSituations":"Stale sockets in /tmp/zellij-<user> after a crash; ZELLIJ_SOCKET_DIR pointing at a read-only mount; upgrading zellij while an old server still runs; permissions (0700) failure on the socket dir.","solutions":["Run the server manually to see the real error: `zellij --server <socket-path> --debug` and read the log","Remove stale session sockets (check `zellij list-sessions`; delete the offending socket dir, e.g. ZELLIJ_SOCKET_DIR entry)","Set ZELLIJ_SOCKET_DIR to a writable location owned by your user, e.g. ZELLIJ_SOCKET_DIR=/tmp/zellij-$USER","Ensure the zellij version is consistent (no half-upgraded binary + running server)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before spawning, verify the environment the server needs:\nuse std::os::unix::fs::PermissionsExt;\nlet sock_dir = zellij_utils::shared::setuid::default_socket_dir(); // or your configured dir\nlet meta = std::fs::metadata(&sock_dir)?;\nassert!(meta.is_dir());\nassert!(meta.permissions().mode() & 0o700 != 0 || meta.uid() == unsafe { libc::getuid() });","typeGuard":null,"tryCatchPattern":"match spawn_server(&socket_path, debug) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"non-zero exit code\") => {\n        eprintln!(\"server failed to start; run `zellij --server {} --debug` for details\", socket_path.display());\n        std::process::exit(1);\n    },\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Clean stale sockets after crashes (zellij delete-all-session / remove the socket dir)","Point ZELLIJ_SOCKET_DIR at a user-owned writable directory","Upgrade client and server together; avoid mixing binaries across versions","When startup fails, reproduce manually with `zellij --server <socket> --debug` and read the log"],"tags":["server","spawn","socket","startup"],"backgroundTag":null,"analyzedSha":"98a0837077492d53dd252ab30bc3e43e41e504f4","analyzedAt":"2026-08-16T13:02:01.396Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}