{"record":{"id":"ee344c0bcdb5a1e9","repo":"Hmbown/CodeWhale","slug":"workspace-path-cannot-be-empty","errorCode":null,"errorMessage":"workspace path cannot be empty","messagePattern":"workspace path cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":5613,"sourceCode":"    if !resolved.starts_with(plugin_path) {\n        anyhow::bail!(\"reviewed plugin MCP path escaped its staged root\");\n    }\n    Ok(resolved)\n}\n\nfn workspace_allows_project_mcp_config(workspace: &Path) -> bool {\n    crate::config::is_workspace_trusted(workspace)\n}\n\nfn checked_workspace_mcp_config_path(workspace: &Path) -> Result<PathBuf> {\n    Ok(checked_workspace_path(workspace)?\n        .join(\".codewhale\")\n        .join(\"mcp.json\"))\n}\n\nfn checked_workspace_path(workspace: &Path) -> Result<PathBuf> {\n    if workspace.as_os_str().is_empty() {\n        anyhow::bail!(\"workspace path cannot be empty\");\n    }\n    if workspace\n        .components()\n        .any(|component| matches!(component, Component::ParentDir))\n    {\n        anyhow::bail!(\"workspace path cannot contain '..' components\");\n    }\n    let absolute = if workspace.is_absolute() {\n        workspace.to_path_buf()\n    } else {\n        std::env::current_dir()\n            .context(\"failed to resolve current directory for workspace\")?\n            .join(workspace)\n    };\n    match absolute.canonicalize() {\n        Ok(path) => Ok(path),\n        Err(err) if err.kind() == std::io::ErrorKind::NotFound => {\n            Ok(normalize_path_components(&absolute))","sourceCodeStart":5595,"sourceCodeEnd":5631,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp.rs#L5595-L5631","documentation":"`checked_workspace_path` rejects an empty workspace path before deriving the project MCP config location (`.codewhale/mcp.json`). An empty `Path` cannot yield a meaningful config file location, so the library fails fast with this validation error instead of writing to a nonsensical path.","triggerScenarios":"Calling any function that passes a `&Path` workspace into `checked_workspace_path` (crates/tui/src/mcp.rs:5613) with `Path::new(\"\")` or `PathBuf::new()` — e.g. when the caller has no workspace loaded yet.","commonSituations":"Launching the TUI outside a project with an unset workspace variable; a caller defaulting a missing CLI flag to an empty string; a config file where the workspace field was dropped or is `\"\"`.","solutions":["Pass a valid absolute workspace path to the API (e.g. `std::env::current_dir()?` when no explicit workspace exists)","Ensure the workspace is resolved and non-empty before calling MCP config functions","If no project is open, avoid project-scope MCP config operations entirely"],"exampleFix":"// before\nlet workspace = PathBuf::from(settings.workspace.unwrap_or_default()); // \"\" when unset\n// after\nlet workspace = settings.workspace.map(PathBuf::from).unwrap_or_else(|| std::env::current_dir().expect(\"cwd\"));","handlingStrategy":"validation","validationCode":"if workspace.as_os_str().is_empty() {\n    return Err(anyhow::anyhow!(\"workspace path cannot be empty\"));\n}","typeGuard":"fn has_workspace(p: &std::path::Path) -> bool { !p.as_os_str().is_empty() }","tryCatchPattern":"match checked_workspace_path(&workspace) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"cannot be empty\") => return Err(ensure_workspace_loaded()),\n    Err(e) => return Err(e),\n}","preventionTips":["Default missing workspaces to std::env::current_dir()","Never default PathBuf options with unwrap_or_default()","Validate workspace presence at startup before MCP config calls"],"tags":["mcp","validation","path","workspace"],"backgroundTag":"empty-required-field","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"}