jdx/mise · error

workspace path {path:?} is absolute; paths must be workspace

Error message

workspace path {path:?} is absolute; paths must be workspace-relative

What it means

normalize_workspace_path() validates every path handed to map_paths_to_projects() / affected_projects_for_paths(): paths must be workspace-relative, and an absolute path is rejected up front. Internally mise always strips the workspace-root prefix before calling these APIs, so a developer calling the graph API directly with filesystem paths (e.g. from a file watcher) hits this check.

Source

Thrown at src/task/workspace.rs:1222

                    );
                }
            }
            Component::RootDir | Component::Prefix(_) => {
                bail!(
                    "workspace project {id:?} has absolute root {root:?}; roots must be workspace-relative"
                );
            }
        }
    }
    if normalized.as_os_str().is_empty() {
        normalized.push(".");
    }
    Ok(normalized)
}

fn normalize_workspace_path(path: &Path) -> Result<PathBuf> {
    if path.is_absolute() {
        bail!("workspace path {path:?} is absolute; paths must be workspace-relative");
    }

    let mut normalized = PathBuf::new();
    for component in path.components() {
        match component {
            Component::CurDir => {}
            Component::Normal(component) => normalized.push(component),
            Component::ParentDir => {
                if !normalized.pop() {
                    bail!("workspace path {path:?} escapes the workspace root");
                }
            }
            Component::RootDir | Component::Prefix(_) => {
                bail!("workspace path {path:?} is absolute; paths must be workspace-relative");
            }
        }
    }
    if normalized.as_os_str().is_empty() {

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Strip the workspace root first: path.strip_prefix(workspace_root) before passing
  2. Emit relative paths at the source (e.g. git -C root diff --relative --name-only)
  3. Filter or skip paths outside the workspace root — they cannot map to projects anyway

Example fix

// before
let map = graph.map_paths_to_projects(["/repo/crates/app/src/lib.rs"])?;

// after
let rel = Path::new("/repo/crates/app/src/lib.rs").strip_prefix("/repo")?;
let map = graph.map_paths_to_projects([rel])?;
Defensive patterns

Strategy: validation

Validate before calling

let rel_paths: Vec<PathBuf> = paths.iter()
    .filter_map(|p| p.strip_prefix(workspace_root).ok().map(Path::to_path_buf))
    .collect();
let map = graph.map_paths_to_projects(rel_paths)?;

Type guard

fn all_paths_workspace_relative<'a>(root: &Path, paths: impl IntoIterator<Item = &'a Path>) -> bool {
    paths.into_iter().all(|p| !p.is_absolute())
}

Try / catch

match graph.affected_projects_for_paths(root, paths, global_inputs) {
    Ok(set) => set,
    Err(err) if err.to_string().contains("is absolute") => {
        let rel: Vec<_> = paths.into_iter().filter_map(|p| p.strip_prefix(root).ok()).collect();
        graph.affected_projects_for_paths(root, rel, global_inputs)?
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Calling graph.map_paths_to_projects(["/home/me/repo/src/main.rs"]) or affected_projects_for_paths(root, [absolute_path], ...) with un-stripped absolute paths; feeding paths from notify/inotify watchers, git diff --name-only run from another cwd, or canonicalized paths.

Common situations: Integrating file-watch/build tooling that natively produces absolute paths; assuming the API takes workspace-rooted absolute paths; inconsistent cwd between path production and graph use.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/d5a7f90a633f1797. Report an issue: GitHub.