{"record":{"id":"c48ccdd89f94e732","repo":"Hmbown/CodeWhale","slug":"mcp-config-path-cannot-be-empty","errorCode":null,"errorMessage":"MCP config path cannot be empty","messagePattern":"MCP config path cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":48,"sourceCode":"mod wire;\n\nuse self::http::{HttpTransport, McpHttpAuth};\nuse self::sse::SseTransport;\nuse self::stdio::StdioTransport;\n#[cfg(all(test, unix))]\nuse self::stdio::{STDIO_SHUTDOWN_GRACE, StderrTail};\nuse self::wire::{is_mcp_stale_session_body, is_mcp_stale_session_error};\nuse crate::network_policy::{Decision, NetworkPolicyDecider, host_from_url};\nuse crate::utils::write_atomic;\n\n// === Error diagnostics helpers (#71) ===\n\n/// Bytes of a non-2xx response body to surface in connection errors.\nconst ERROR_BODY_PREVIEW_BYTES: usize = 200;\n\nfn validate_mcp_config_path(path: &Path) -> Result<()> {\n    if path.as_os_str().is_empty() {\n        anyhow::bail!(\"MCP config path cannot be empty\");\n    }\n    if path\n        .components()\n        .any(|component| matches!(component, Component::ParentDir))\n    {\n        anyhow::bail!(\"MCP config path cannot contain '..' components\");\n    }\n    Ok(())\n}\n\n/// Expand `${NAME}` placeholders in an MCP config value from the process\n/// environment. This lets secrets (API keys, bearer tokens, …) be supplied\n/// through environment variables instead of being written in cleartext into\n/// the MCP config file on disk.\n///\n/// On a missing or malformed placeholder the error names only the offending\n/// variable, never the surrounding value, so a secret-bearing string is never\n/// echoed into logs or error output.","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/mcp.rs#L30-L66","documentation":"validate_mcp_config_path rejects MCP config paths whose OsStr is empty before any filesystem access. It exists so downstream code never attempts directory creation or writes against an empty path; the companion check in the same validator rejects '..' components.","triggerScenarios":"Passing an empty config path: an empty --mcp-config style flag value, or an environment variable or config field that expands to the empty string when the MCP config is loaded or saved.","commonSituations":"Unset environment variables used for the config path, empty strings forwarded by wrapper scripts, misconfigured CI variables, programmatic callers passing user input unchecked.","solutions":["Supply a real, preferably absolute, path for the MCP config file","If the path comes from an environment variable, ensure it is set and non-empty before invoking the command","Fall back to the documented default config location instead of forwarding an empty override"],"exampleFix":"# before\nMCP_CONFIG= codewhale mcp list   # error: MCP config path cannot be empty\n# after\nMCP_CONFIG=\"$HOME/.config/codewhale/mcp.json\" codewhale mcp list","handlingStrategy":"validation","validationCode":"// Resolve an override that may be unset or empty into a concrete path\nfn resolve_config_path(raw: Option<&str>) -> std::path::PathBuf {\n    raw.map(str::trim)\n        .filter(|s| !s.is_empty())\n        .map(std::path::PathBuf::from)\n        .unwrap_or_else(default_mcp_config_path)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate CLI and env path overrides for non-empty before use","Always have a documented default config path","Fail fast in wrappers when required variables expand to empty"],"tags":["mcp","config","validation","path"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}