{"record":{"id":"60cf5503210dbb12","repo":"elkowar/eww","slug":"failed-to-start-command-execution-thread","errorCode":null,"errorMessage":"Failed to start command-execution-thread","messagePattern":"Failed to start command-execution-thread","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eww/src/widgets/mod.rs","lineNumber":41,"sourceCode":"        .name(\"command-execution-thread\".to_string())\n        .spawn(move || {\n            log::debug!(\"Running command from widget [timeout: {}ms]: {}\", timeout.as_millis(), cmd);\n            let child = Command::new(\"/bin/sh\").arg(\"-c\").arg(&cmd).spawn();\n            match child {\n                Ok(mut child) => match child.wait_timeout(timeout) {\n                    // child timed out\n                    Ok(None) => {\n                        log::error!(\"WARNING: command {} timed out\", &cmd);\n                        let _ = child.kill();\n                        let _ = child.wait();\n                    }\n                    Err(err) => log::error!(\"Failed to execute command {}: {}\", cmd, err),\n                    Ok(Some(_)) => {}\n                },\n                Err(err) => log::error!(\"Failed to launch child process: {}\", err),\n            }\n        })\n        .expect(\"Failed to start command-execution-thread\");\n}\n\nfn replace_placeholders<T>(cmd: &str, args: &[T]) -> String\nwhere\n    T: 'static + std::fmt::Display + Send + Sync + Clone,\n{\n    if !args.is_empty() {\n        let cmd = cmd.replace(\"{}\", &format!(\"{}\", args[0]));\n        args.iter().enumerate().fold(cmd, |acc, (i, arg)| acc.replace(&format!(\"{{{}}}\", i), &format!(\"{}\", arg)))\n    } else {\n        cmd.to_string()\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    #[test]","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/eww/src/widgets/mod.rs#L23-L59","documentation":"run_command spawns a thread per executed widget command; the expect panics if std::thread::Builder::spawn fails. Like all spawn failures this is an OS resource error (thread limit, memory), not a problem with the command string itself.","triggerScenarios":"Clicking a widget button (or any command-triggering widget) while the process is at its thread limit: RLIMIT_NPROC exhausted, pids cgroup cap, or out-of-memory at pthread_create.","commonSituations":"Configs with many frequently-clicked widgets leaking threads over a long session, containers with tiny pids limits, or heavily loaded shared machines.","solutions":["Raise limits: `ulimit -u`, systemd TasksMax, container --pids-limit.","Restart the eww daemon to clear leaked threads, then investigate why threads accumulated.","Avoid spawning per command: reuse a worker/thread-pool or an async runtime for widget commands.","Propagate/log the io::Error instead of panicking so a failed command click doesn't kill the whole daemon."],"exampleFix":"// before\nstd::thread::Builder::new().name(...).spawn(move || { ... }).expect(\"Failed to start command-execution-thread\");\n// after\nif let Err(e) = std::thread::Builder::new().name(\"command-execution\".to_string()).spawn(move || { ... }) {\n    log::error!(\"Failed to start command-execution-thread: {}\", e);\n}","handlingStrategy":"try-catch","validationCode":"let ok = rlimit::getrlimit(rlimit::Resource::NPROC).map(|l| l.0 > 32).unwrap_or(true);\nif !ok { log::warn!(\"thread limit low; widget commands may fail to spawn\"); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = std::thread::Builder::new().name(\"cmd-exec\".into()).spawn(work) {\n    log::error!(\"Failed to start command-execution-thread: {}\", e);\n}","preventionTips":["Don't spawn a fresh thread per click; reuse a small worker pool","Raise ulimit -u / TasksMax on desktop sessions","Restart long-running daemons that accumulate threads","Log spawn failures instead of panicking the whole UI"],"tags":["threads","spawn","widgets","resource-limits"],"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"}