{"record":{"id":"274e41a73daad165","repo":"Hmbown/CodeWhale","slug":"mcp-server-has-no-command-configured","errorCode":null,"errorMessage":"MCP server '{}' has no command configured","messagePattern":"MCP server '(.+?)' has no command configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/stdio_client.rs","lineNumber":501,"sourceCode":"impl ChildProcessMcpClient {\n    /// Spawn `config.command` with `config.args`/`config.env` and complete the\n    /// MCP handshake.\n    ///\n    /// Returns `Err` — never a degraded-but-usable client — when the command\n    /// cannot be executed, exits immediately, or does not answer `initialize`\n    /// within `HANDSHAKE_TIMEOUT`.\n    pub fn spawn(config: &McpServerConfig) -> Result<Self> {\n        Self::spawn_with_timeouts(config, HANDSHAKE_TIMEOUT, REQUEST_TIMEOUT)\n    }\n\n    fn spawn_with_timeouts(\n        config: &McpServerConfig,\n        handshake_timeout: Duration,\n        request_timeout: Duration,\n    ) -> Result<Self> {\n        let server_name = config.name.clone();\n        if config.command.trim().is_empty() {\n            bail!(\"MCP server '{server_name}' has no command configured\");\n        }\n\n        let mut command = Command::new(&config.command);\n        command\n            .args(&config.args)\n            .envs(&config.env)\n            .stdin(Stdio::piped())\n            .stdout(Stdio::piped())\n            // The child's diagnostics belong on our stderr: stdout is the\n            // JSON-RPC channel and must not be polluted, and swallowing the\n            // child's stderr is how a misconfigured server becomes a silent\n            // one.\n            .stderr(Stdio::inherit());\n\n        // Own descendants too: shell/package launchers can exit before the\n        // actual server, leaving it alive with inherited protocol pipes.\n        #[cfg(unix)]\n        command.process_group(0);","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/mcp/src/stdio_client.rs#L483-L519","documentation":"`spawn_with_timeouts` refuses to launch an MCP server subprocess whose configured `command` is empty or whitespace-only. There is no executable to spawn, so the client fails immediately with a clear config error instead of an obscure spawn failure deeper in `Command::new`. This is a configuration precondition check.","triggerScenarios":"Calling `spawn_with_timeouts` (typically via client construction) with an `McpServerConfig` whose `command` field is `\"\"`, contains only spaces, or was never set (defaulting to empty).","commonSituations":"A config file entry for the server missing the `command` key; an environment-variable interpolation that resolved to empty (e.g. `${MY_MCP_BIN}` unset); copy-pasting a server entry and forgetting to fill in the command; a tool generating configs that writes blank commands when discovery fails.","solutions":["Set a valid, absolute path to the MCP server executable in the `command` field of the server's config.","If the command comes from an environment variable, verify that variable is set in the environment the client runs in.","If the server should run via a runtime (node/python), point command at the runtime binary and put the script in `args`.","Validate config entries at load time so empty commands are rejected before they reach spawn."],"exampleFix":"// before: config with empty command\n{\"name\":\"filesystem\",\"command\":\"\",\"args\":[\"-y\",\"@modelcontextprotocol/server-filesystem\",\"/tmp\"]}\n// after: real executable\n{\"name\":\"filesystem\",\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-filesystem\",\"/tmp\"]}","handlingStrategy":"validation","validationCode":"fn validate_mcp_config(cfg: &McpServerConfig) -> Result<(), String> {\n    if cfg.command.trim().is_empty() {\n        return Err(format!(\"server '{}' has empty command\", cfg.name));\n    }\n    Ok(())\n}\n// call for every entry when configs load\nfor c in &configs { validate_mcp_config(c)?; }","typeGuard":null,"tryCatchPattern":"match spawn_with_timeouts(&config, hs, req).await {\n    Err(e) if e.to_string().contains(\"no command configured\") => {\n        eprintln!(\"fill in the `command` field for server '{}' in your config\", config.name);\n    }\n    other => other,\n}","preventionTips":["Validate all MCP server configs at startup, before any spawn.","Use absolute paths or well-known runtime binaries (npx, python3) for commands.","If commands come from env vars, fail fast at config load when they resolve empty."],"tags":["mcp","configuration","empty-command","spawn"],"backgroundTag":"missing-required-config-field","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}