{"record":{"id":"c575d9b3e173d45d","repo":"Hmbown/CodeWhale","slug":"failed-to-inherit-reviewed-plugin-executable-descr","errorCode":null,"errorMessage":"failed to inherit reviewed plugin executable descriptor","messagePattern":"failed to inherit reviewed plugin executable descriptor","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":926,"sourceCode":"            .iter()\n            .map(|byte| format!(\"{byte:02x}\"))\n            .collect::<String>();\n        if &actual != expected {\n            anyhow::bail!(\"reviewed plugin executable bytes changed before spawn\");\n        }\n        file.seek(std::io::SeekFrom::Start(0))\n            .context(\"rewind reviewed launch file after verification\")?;\n\n        #[cfg(unix)]\n        let launch_path = {\n            use std::os::fd::AsRawFd as _;\n            let fd = file.as_raw_fd();\n            // SAFETY: `fd` is owned by `file`; clearing only FD_CLOEXEC keeps\n            // that same descriptor available across the imminent exec.\n            let flags = unsafe { libc::fcntl(fd, libc::F_GETFD) };\n            if flags < 0 || unsafe { libc::fcntl(fd, libc::F_SETFD, flags & !libc::FD_CLOEXEC) } < 0\n            {\n                anyhow::bail!(\"failed to inherit reviewed plugin executable descriptor\");\n            }\n            #[cfg(target_os = \"linux\")]\n            let prefix = \"/proc/self/fd\";\n            #[cfg(not(target_os = \"linux\"))]\n            let prefix = \"/dev/fd\";\n            std::ffi::OsString::from(format!(\"{prefix}/{fd}\"))\n        };\n\n        #[cfg(not(unix))]\n        let launch_path = path.as_os_str().to_os_string();\n\n        self.opened_files.push(file);\n        Ok(launch_path)\n    }\n\n    fn bind_cwd(&mut self, cwd: &Path) -> Result<()> {\n        #[cfg(unix)]\n        {","sourceCodeStart":908,"sourceCodeEnd":944,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L908-L944","documentation":"On Unix, the reviewed-plugin launcher keeps the verified executable's file descriptor open across execve by clearing FD_CLOEXEC via fcntl(F_SETFD), then spawns through /proc/self/fd/N (or /dev/fd/N). This error means fcntl(F_GETFD) or fcntl(F_SETFD) returned a negative result on that descriptor (crates/tui/src/mcp.rs:924-927), so descriptor-based launch cannot be guaranteed and the spawn aborts before any exec.","triggerScenarios":"fcntl failing with EBADF because the descriptor was closed concurrently by another thread/task, fd-table pressure, or a seccomp/sandbox profile denying fcntl. Cannot fire in normal operation.","commonSituations":"Embedders or test harnesses that aggressively close inherited fds before spawn; restrictive containers (gVisor, seccomp filters); fd-limit exhaustion with many concurrent MCP connections.","solutions":["Retry the connection once - a fresh open yields a fresh descriptor and normally succeeds.","Check fd pressure: ulimit -n and the count in /proc/<pid>/fd; raise the limit if near exhaustion.","Audit embedding code for loops that close foreign descriptors (pre-exec hygiene like `for fd in 3..N { close(fd) }`) and exclude this one.","If it reproduces under a sandbox/seccomp profile, permit fcntl(F_GETFD/F_SETFD) or report a bug with an strace."],"exampleFix":"// before: single attempt; a rare EBADF aborts plugin spawn\nlet conn = McpConnection::connect_with_policy(name, cfg, &timeouts, policy).await?;\n// after: retry once - descriptor races are transient\nlet conn = match McpConnection::connect_with_policy(name, cfg.clone(), &timeouts, policy).await {\n    Ok(conn) => conn,\n    Err(err) if err.to_string().contains(\"failed to inherit reviewed plugin\") => {\n        McpConnection::connect_with_policy(name, cfg, &timeouts, policy).await?\n    }\n    Err(err) => return Err(err),\n};","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let conn = match McpConnection::connect_with_policy(name, cfg.clone(), &timeouts, policy).await {\n    Ok(conn) => conn,\n    Err(err) if err.to_string().contains(\"failed to inherit reviewed plugin\") => {\n        // Transient descriptor race: one retry on a freshly opened file.\n        McpConnection::connect_with_policy(name, cfg, &timeouts, policy).await?\n    }\n    Err(err) => return Err(err),\n};","preventionTips":["Raise RLIMIT_NOFILE (ulimit -n) when running many MCP connections.","Never close file descriptors you do not own in pre-exec or embedder code.","If running under seccomp/sandbox profiles, allow fcntl(F_GETFD/F_SETFD)."],"tags":["unix","file-descriptor","spawn","plugin","mcp"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}