jdx/mise · error
relative repo path `{path_raw}` must stay within the project
Error message
relative repo path `{path_raw}` must stay within the project root (no `..` or absolute segments) What it means
After a project root is found, each component of the relative repo path is inspected; any `..` (ParentDir), root `/` (RootDir), or Windows drive-prefix (Prefix) component means the path could point outside the project root, and from_toml rejects it. This is a containment guard: with a relative key, bootstrap only manages checkouts inside the project. Repos elsewhere must use `~/` or absolute paths.
Source
Thrown at src/system/repos.rs:100
"repo path `{path_raw}` cannot start with `~`; use `~/` for a home-relative path"
);
}
let path = file::replace_path(&path_raw);
let path = if path.is_absolute() {
path
} else {
let Some(root) = project_root else {
bail!(
"relative repo paths are only allowed in a project config; use an absolute path or a `~/` path"
);
};
if path.components().any(|component| {
matches!(
component,
Component::ParentDir | Component::RootDir | Component::Prefix(_)
)
}) {
bail!(
"relative repo path `{path_raw}` must stay within the project root (no `..` or absolute segments)"
);
}
if !path
.components()
.any(|component| matches!(component, Component::Normal(_)))
{
bail!(
"relative repo path `{path_raw}` must name a directory inside the project root"
);
}
// Join only the Normal segments so `./foobar` resolves to
// `<root>/foobar` rather than `<root>/./foobar` — a `.` component
// survives `Path::join` and leaks into every displayed path.
let mut resolved = root.to_path_buf();
for component in path.components() {
if let Component::Normal(segment) = component {
resolved.push(segment);View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Point the key inside the project (drop the `..` segments)
- Use a `~/` path such as `"~/src/shared"` for repos that live outside the project
- Use an absolute path for machine-specific locations
Example fix
# before
[bootstrap.repos]
"../shared" = { url = "git@github.com:team/shared.git" }
# after
[bootstrap.repos]
"~/src/shared" = { url = "git@github.com:team/shared.git" } Defensive patterns
Strategy: validation
Validate before calling
use std::path::{Component, Path};
fn repo_path_stays_in_root(path_raw: &str) -> bool {
!Path::new(path_raw).components().any(|c| {
matches!(c, Component::ParentDir | Component::RootDir | Component::Prefix(_))
})
} Type guard
fn is_contained_relative_repo_path(path_raw: &str) -> bool {
!std::path::Path::new(path_raw)
.components()
.any(|c| matches!(c, std::path::Component::ParentDir | std::path::Component::RootDir | std::path::Component::Prefix(_)))
} Prevention
- Reserve relative repo keys for checkouts inside the project tree
- Use `~/` paths for sibling or home-based repos
- Never build repo keys by concatenating user input containing `..`
When it happens
Trigger: Keys like `"../shared"`, `"vendor/../../escape"`, or (on Windows) a key embedding a `C:\` prefix inside an otherwise relative path, in a project mise.toml.
Common situations: Repos intentionally stored as siblings of the project (`../lib/foo`); refactoring from absolute to relative paths; monorepo layouts where the checkout lives one level above the config.
Related errors
- relative repo paths are only allowed in a project config; us
- relative repo path `{path_raw}` must name a directory inside
- no configured repo matched path: {filter}
- --localized-dir {raw:?} cannot be carried to Windows: {bad:?
- bootstrap user '{name}' {field} must be an absolute path
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/738ec9c87cdcf9c1.
Report an issue: GitHub.