{"record":{"id":"8b619aa9261fd762","repo":"xai-org/grok-build","slug":"failed-to-exec-program-err","errorCode":null,"errorMessage":"failed to exec {program}: {err}","messagePattern":"failed to exec (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/wrap_cmd.rs","lineNumber":199,"sourceCode":"    if !cfg!(any(unix, windows)) {\n        return false;\n    }\n\n    use std::io::IsTerminal;\n    std::io::stdin().is_terminal()\n        && std::io::stdout().is_terminal()\n        && std::io::stderr().is_terminal()\n}\n\n/// Replace the current process with `program <args...>` (no PTY wrapping).\n#[cfg(unix)]\nfn exec_command(program: &str, args: &[String]) -> Result<()> {\n    use std::os::unix::process::CommandExt;\n\n    let err = std::process::Command::new(program).args(args).exec();\n\n    // exec() only returns on error.\n    Err(anyhow::anyhow!(\"failed to exec {program}: {err}\"))\n}\n\n/// On non-Unix platforms, spawn and wait.\n#[cfg(not(unix))]\nfn exec_command(program: &str, args: &[String]) -> Result<()> {\n    let status = std::process::Command::new(program)\n        .args(args)\n        .status()\n        .map_err(|e| anyhow::anyhow!(\"failed to run {program}: {e}\"))?;\n\n    std::process::exit(status.code().unwrap_or(1));\n}\n\n#[cfg(all(test, unix))]\n#[path = \"wrap_cmd_tests.rs\"]\nmod tests;\n","sourceCodeStart":181,"sourceCodeEnd":216,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/wrap_cmd.rs#L181-L216","documentation":"On Unix, `exec_command` uses `std::os::unix::process::CommandExt::exec`, which replaces the current process and only ever returns if the program could not be executed (not found, permission denied, exec format error). The library wraps that errno error in an anyhow error naming the program. It means the wrapper could not hand off to the target binary at all.","triggerScenarios":"The wrapped program name does not exist on PATH; the file exists but lacks the execute bit; the binary is for a different architecture (ENOEXEC); a shebang points at a missing interpreter.","commonSituations":"PATH altered inside a sandboxed wrapper so the target binary is invisible; user moved/renamed the tool the wrapper delegates to; running a macOS binary on Linux; node_modules bin scripts losing +x after a bad copy.","solutions":["Run `which <program>` in the same environment to confirm the binary resolves on PATH.","Check the execute permission bit (`ls -l`, `chmod +x`) on the target binary.","Verify the binary matches the platform architecture (`file <program>`).","If invoked with a relative path, use an absolute path or resolve it programmatically before exec.","Inspect the inner errno in `{err}` (NotFound vs PermissionDenied vs ExecFormatError) to pinpoint the cause."],"exampleFix":"// before\nexec_command(\"grok-sandboxed-tool\", &args)?; // relies on PATH inside sandbox\n// after\nlet program = which::which(\"grok-sandboxed-tool\")\n    .map_err(|_| anyhow::anyhow!(\"grok-sandboxed-tool not found on PATH\"))?\n    .to_string_lossy().to_string();\nexec_command(&program, &args)?;","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn can_exec(program: &str) -> Result<(), String> {\n    if program.contains('/') {\n        let p = Path::new(program);\n        if !p.exists() { return Err(format!(\"{program} does not exist\")); }\n        return std::fs::metadata(p)\n            .map(|m| m.permissions().mode() & 0o111 != 0)\n            .map_err(|e| e.to_string())\n            .and_then(|x| if x { Ok(()) } else { Err(format!(\"{program} not executable\")) });\n    }\n    let path = std::env::var(\"PATH\").unwrap_or_default();\n    for dir in path.split(':') {\n        let candidate = Path::new(dir).join(program);\n        if candidate.is_file() { return Ok(()); }\n    }\n    Err(format!(\"{program} not found on PATH\"))\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = exec_command(program, &args) {\n    let msg = e.to_string();\n    if msg.contains(\"No such file\") {\n        eprintln!(\"program '{program}' not found; check PATH\");\n    } else if msg.contains(\"Permission denied\") {\n        eprintln!(\"program '{program}' is not executable; chmod +x\");\n    } else {\n        eprintln!(\"exec failed: {e:#}\");\n    }\n    std::process::exit(127);\n}","preventionTips":["Resolve program paths explicitly (which/absolute path) instead of relying on PATH inside sandboxes.","Check execute permissions after copying or installing binaries.","Verify binary architecture matches the host (`file <program>`).","Keep PATH stable and documented for wrapper entry points."],"tags":["rust","process-exec","unix","exec","path"],"backgroundTag":"exec-program-not-found","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}