Hmbown/CodeWhale · error

workspace path cannot be empty

Error message

workspace path cannot be empty

What it means

checked_workspace_path is the entry guard for workspace-scoped MCP config lookups. An empty workspace string cannot identify a workspace, so it is rejected immediately, before any path is joined or the filesystem is touched.

Source

Thrown at crates/tui/src/mcp.rs:3833

    if !resolved.starts_with(plugin_path) {
        anyhow::bail!("reviewed plugin MCP path escaped its staged root");
    }
    Ok(resolved)
}

fn workspace_allows_project_mcp_config(workspace: &Path) -> bool {
    crate::config::is_workspace_trusted(workspace)
}

fn checked_workspace_mcp_config_path(workspace: &Path) -> Result<PathBuf> {
    Ok(checked_workspace_path(workspace)?
        .join(".codewhale")
        .join("mcp.json"))
}

fn checked_workspace_path(workspace: &Path) -> Result<PathBuf> {
    if workspace.as_os_str().is_empty() {
        anyhow::bail!("workspace path cannot be empty");
    }
    if workspace
        .components()
        .any(|component| matches!(component, Component::ParentDir))
    {
        anyhow::bail!("workspace path cannot contain '..' components");
    }
    let absolute = if workspace.is_absolute() {
        workspace.to_path_buf()
    } else {
        std::env::current_dir()
            .context("failed to resolve current directory for workspace")?
            .join(workspace)
    };
    match absolute.canonicalize() {
        Ok(path) => Ok(path),
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
            Ok(normalize_path_components(&absolute))

View on GitHub (pinned to 8880682c63)

Solutions

  1. Pass a non-empty workspace path (preferably absolute) from the caller
  2. Default to std::env::current_dir() when the workspace is unknown
  3. Fix the upstream config/CLI plumbing that produced the empty string

Example fix

// before
let path = checked_workspace_mcp_config_path(Path::new(&workspace_var))?;

// after
let workspace = if workspace_var.is_empty() {
    std::env::current_dir()?
} else {
    PathBuf::from(&workspace_var)
};
let path = checked_workspace_mcp_config_path(&workspace)?;
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty workspaces at the boundary before any MCP config lookup:
let workspace = if workspace_input.as_os_str().is_empty() {
    std::env::current_dir().context("no workspace supplied; using cwd")?
} else {
    workspace_input.to_path_buf()
};
let mcp_path = checked_workspace_mcp_config_path(&workspace)?;

Type guard

fn is_usable_workspace(p: &std::path::Path) -> bool {
    !p.as_os_str().is_empty()
        && !p.components().any(|c| matches!(c, std::path::Component::ParentDir))
}

Prevention

When it happens

Trigger: Passing an empty workspace (an unpopulated config field, an env var that expanded to nothing, or an empty string from argument parsing) into project MCP config loading or the checked_workspace_mcp_config_path helper.

Common situations: Calling workspace MCP helpers from scripts or tests with an uninitialized workspace variable; a launcher that starts the TUI before setting the workspace.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/ee344c0bcdb5a1e9. Report an issue: GitHub.