{"record":{"id":"091f4491f6c81ff4","repo":"elkowar/eww","slug":"failed-to-start-outer-main-async-runtime-thread","errorCode":null,"errorMessage":"Failed to start outer-main-async-runtime thread","messagePattern":"Failed to start outer-main-async-runtime thread","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/eww/src/server.rs","lineNumber":205,"sourceCode":"                let forward_exit_to_app_handle = {\n                    let ui_send = ui_send.clone();\n                    tokio::spawn(async move {\n                        // Wait for application exit event\n                        let _ = crate::application_lifecycle::recv_exit().await;\n                        log::debug!(\"Forward task received exit event\");\n                        // Then forward that to the application\n                        let _ = ui_send.send(app::DaemonCommand::KillServer);\n                    })\n                };\n\n                let result = tokio::try_join!(filewatch_join_handle, ipc_server_join_handle, forward_exit_to_app_handle);\n\n                if let Err(e) = result {\n                    log::error!(\"Eww exiting with error: {:?}\", e);\n                }\n            })\n        })\n        .expect(\"Failed to start outer-main-async-runtime thread\");\n\n    handle\n}\n\n/// Watch configuration files for changes, sending reload events to the eww app when the files change.\nasync fn run_filewatch<P: AsRef<Path>>(config_dir: P, evt_send: UnboundedSender<app::DaemonCommand>) -> Result<()> {\n    use notify::{RecommendedWatcher, RecursiveMode, Watcher};\n\n    let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();\n    let mut watcher: RecommendedWatcher = notify::recommended_watcher(move |res: notify::Result<notify::Event>| match res {\n        Ok(notify::Event { kind: notify::EventKind::Modify(_), paths, .. }) => {\n            let relevant_files_changed = paths.iter().any(|path| {\n                let ext = path.extension().unwrap_or_default();\n                ext == \"yuck\" || ext == \"scss\" || ext == \"css\"\n            });\n            if relevant_files_changed {\n                if let Err(err) = tx.send(()) {\n                    log::warn!(\"Error forwarding file update event: {:?}\", err);","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/eww/src/server.rs#L187-L223","documentation":"std::thread::Builder::spawn failed while starting the 'outer-main-async-runtime' thread that hosts the tokio runtime; the expect turns the io::Error into a panic. Spawn failures are OS resource errors: the process or user hit its thread/process limit or the system ran out of memory.","triggerScenarios":"init_async_part spawning the outer thread when RLIMIT_NPROC is exhausted, the pids cgroup limit is reached, or pthread_create fails with EAGAIN/ENOMEM.","commonSituations":"Long-running desktop sessions that leaked threads, minimal containers (small pids.max), shared accounts over their process quota, or systems under severe memory pressure.","solutions":["Check thread/process usage for the user (`ps -o nlwp -p $$`, `ulimit -u`) and raise RLIMIT_NPROC or systemd TasksMax.","Kill leaked processes/threads belonging to the user, then restart the eww daemon.","Raise container pids limit (docker `--pids-limit`, k8s pod pids limit).","Handle the error instead of panicking: log it and shut the daemon down with a diagnostic."],"exampleFix":"// before\nstd::thread::Builder::new()\n    .name(\"outer-main-async-runtime\".to_string())\n    .spawn(move || { /* ... */ })\n    .expect(\"Failed to start outer-main-async-runtime thread\");\n// after\nstd::thread::Builder::new()\n    .name(\"outer-main-async-runtime\".to_string())\n    .spawn(move || { /* ... */ })\n    .context(\"Failed to start outer-main-async-runtime thread (check ulimit -u / TasksMax)\")?;","handlingStrategy":"try-catch","validationCode":"// check spawn headroom before starting\nlet n = std::fs::read_dir(\"/proc/self/task\").map(|d| d.count()).unwrap_or(0);\nif n > 500 { log::warn!(\"high thread count: {}\", n); }","typeGuard":null,"tryCatchPattern":"match std::thread::Builder::new().name(\"outer-main-async-runtime\".into()).spawn(work) {\n    Ok(h) => h,\n    Err(e) => { log::error!(\"thread spawn failed: {}\", e); return; }\n}","preventionTips":["Keep RLIMIT_NPROC well above expected thread usage","Kill leaked eww daemons (eww kill) instead of stacking instances","Set TasksMax=infinity on user services that spawn threads","Watch for ENOMEM/EAGAIN under memory pressure"],"tags":["threads","spawn","resource-limits","tokio"],"backgroundTag":"resource-exhaustion","analyzedSha":"48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa","analyzedAt":"2026-09-08T03:13:26.897Z","contentChangedAt":"2026-09-08T03:13:26.897Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}