{"record":{"id":"41cc5e0415f5f530","repo":"epi052/feroxbuster","slug":"failed-to-spawn-a-child-process","errorCode":null,"errorMessage":"failed to spawn a child process","messagePattern":"failed to spawn a child process","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/main.rs","lineNumber":484,"sourceCode":"                cloned[out_idx + 1] = full_path;\n            }\n\n            cloned.push(\"-u\".to_string());\n            cloned.push(target);\n\n            let bin = cloned.index(0).to_owned(); // user's path to feroxbuster\n            let args = cloned.index(1..).to_vec(); // and args\n\n            let permit = PARALLEL_LIMITER.acquire().await?;\n\n            log::debug!(\"parallel exec: {} {}\", bin, args.join(\" \"));\n\n            tokio::task::spawn(async move {\n                let mut output = Command::new(bin)\n                    .args(&args)\n                    .stdout(Stdio::piped())\n                    .spawn()\n                    .expect(\"failed to spawn a child process\");\n\n                let stdout = output.stdout.take().unwrap();\n\n                let mut bufread = BufReader::new(stdout);\n                // output for a single line is a minimum of 51 bytes, so we'll start with that\n                // + a little wiggle room, and grow as needed\n                let mut buf: String = String::with_capacity(128);\n\n                while let Ok(n) = bufread.read_line(&mut buf) {\n                    if n > 0 {\n                        let trimmed = buf.trim();\n                        if !trimmed.is_empty() {\n                            println!(\"{trimmed}\");\n                        }\n                        buf.clear();\n                    } else {\n                        break;\n                    }","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/epi052/feroxbuster/blob/1f595dab5c76858d5a14fbc47dabf2563d729c62/src/main.rs#L466-L502","documentation":"wrapped_main spawns a helper child process (a binary) with tokio::process::Command to stream output. Command::spawn().expect(...) panics if the OS cannot spawn the child, producing 'failed to spawn a child process'.","triggerScenarios":"Calling wrapped_main when the resolved child binary cannot be executed: binary missing at that path, missing execute permission, exec hitting resource limits (fork/ENOMEM, pid limits), or a seccomp/container policy blocking exec.","commonSituations":"Running inside minimal Docker images with restricted rlimits, sandboxed CI runners blocking process creation, or the binary having been moved/deleted while running.","solutions":["Ensure the child binary exists and is executable at the resolved path (chmod +x)","Raise container/sandbox rlimits (e.g. ulimit -u, docker --pids-limit) or allow process spawning in your security policy","Check for PID exhaustion (too many processes) and free resources, then rerun"],"exampleFix":"// before (shell)\n./feroxbuster # not executable / noexec volume\n// after (shell)\nchmod +x ./feroxbuster && ./feroxbuster","handlingStrategy":"retry","validationCode":"let bin_ok = std::path::Path::new(&bin).exists();\nlet can_exec = bin_ok && std::fs::metadata(&bin).map(|m| m.permissions().readonly() == false).unwrap_or(false);","typeGuard":"fn spawnable(bin: &str) -> bool { std::path::Path::new(bin).exists() }","tryCatchPattern":"match Command::new(&bin).args(&args).stdout(Stdio::piped()).spawn() {\n  Ok(child) => stream(child),\n  Err(e) => eprintln!(\"spawn failed ({e}); check binary path/permissions/limits\"),\n}","preventionTips":["Ensure the binary exists and has the execute bit set","Raise rlimits/pids-limit in containers and CI sandboxes","Avoid running from noexec-mounted volumes"],"tags":["process","spawn","panic","runtime"],"backgroundTag":"command-not-found","analyzedSha":"1f595dab5c76858d5a14fbc47dabf2563d729c62","analyzedAt":"2026-09-13T19:33:06.208Z","contentChangedAt":"2026-09-13T19:33:06.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}