{"record":{"id":"81e589ab1e51ed41","repo":"Hmbown/CodeWhale","slug":"mcp-stdio-spawn-failed-transport-stdio-server-server-name","errorCode":null,"errorMessage":"MCP stdio spawn failed (transport=stdio server={server_name} cmd={command:?} args={:?} env_keys={env_keys:?})","messagePattern":"MCP stdio spawn failed \\(transport=stdio server=(.+?) cmd=(.+?) args=(.+?) env_keys=(.+?)\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp/stdio.rs","lineNumber":184,"sourceCode":"            let message = if error.kind() == std::io::ErrorKind::NotFound\n                && super::is_node_command(command)\n                && launch_cwd.is_none_or(|directory| directory.is_dir())\n            {\n                format!(\"MCP server {server_name} could not start because Node.js was not found. Install Node.js from https://nodejs.org/ and restart Codewhale with node on PATH. Built-in Computer Use requires Node.js 20 or newer.\")\n            } else if config.reviewed_plugin.is_some() {\n                format!(\n                    \"MCP stdio spawn failed (transport=stdio server={server_name} reviewed-plugin argv_count={} env_count={})\",\n                    config.args.len(),\n                    expanded_env.len(),\n                )\n            } else {\n                let env_keys: Vec<&str> = expanded_env.keys().map(String::as_str).collect();\n                format!(\n                    \"MCP stdio spawn failed (transport=stdio server={server_name} cmd={command:?} args={:?} env_keys={env_keys:?})\",\n                    config.args,\n                )\n            };\n            anyhow::Error::new(error).context(message)\n        })?;\n\n        let stdin = child.stdin.take().context(\"Failed to get MCP stdin\")?;\n        let stdout = child.stdout.take().context(\"Failed to get MCP stdout\")?;\n        let stderr = child.stderr.take().context(\"Failed to get MCP stderr\")?;\n\n        // Drain stderr into a bounded ring buffer so a crash mid-run leaves\n        // diagnostic breadcrumbs instead of disappearing into `Stdio::null`.\n        // The task exits naturally when the child closes its stderr\n        // (kill_on_drop / exit / explicit shutdown).\n        let stderr_tail = StderrTail::new();\n        {\n            let tail = Arc::clone(&stderr_tail);\n            // A reviewed plugin child receives environment-backed values that\n            // are intentionally absent from its manifest. Still drain its\n            // stderr to avoid blocking, but do not retain or surface arbitrary\n            // child output that could echo those credentials into a chat or\n            // persisted transcript.","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp/stdio.rs#L166-L202","documentation":"When spawning an MCP stdio server process fails, spawn builds a diagnostic message embedding the transport, server name, command, args, and only the env variable NAMES (never values) before attaching the original error as context. This gives enough detail to debug the launch without leaking secrets.","triggerScenarios":"Child-process spawn fails for an MCP server configured with transport=stdio: the command binary does not exist, is not executable, the working directory is missing, or env expansion yields an unusable command.","commonSituations":"Server command not installed or not on PATH (e.g. npx/uvx missing); wrong path in config; missing execute bit; typo in command name; interpreter version too old.","solutions":["Run the configured command and args by hand in a shell to see the OS-level error.","Install the server binary or fix its absolute path in the MCP server config.","Verify required env vars referenced by the config are set (only their keys appear in the message).","Check execute permissions on the command file."],"exampleFix":"// before: config\n\"command\": \"my-mcp-server\"\n// after: install it or use an absolute path\n\"command\": \"/usr/local/bin/my-mcp-server\"","handlingStrategy":"validation","validationCode":"let which = which(&command);\nif which.is_none() { eprintln!(\"command not found: {command}\"); }\n// also verify execute bit: metadata.permissions().mode() & 0o111 != 0","typeGuard":null,"tryCatchPattern":"match spawn().await {\n    Err(e) if e.to_string().contains(\"MCP stdio spawn failed\") => {\n        eprintln!(\"{e:#}; install the server binary or fix the configured path\");\n    }\n    other => other?,\n}","preventionTips":["Install MCP server binaries before configuring them, and verify with `command -v`.","Prefer absolute paths or pinned versions (npx pkg@version) in server configs.","Keep required env vars set in the launch environment (only names are logged, never values)."],"tags":["mcp","stdio","process-spawn","command-not-found"],"backgroundTag":"command-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}