jdx/mise · error

relative repo path ` ` must name a directory inside the…

Error message

relative repo path `{path_raw}` must name a directory inside the project root

What it means

After rejecting traversal components, from_toml requires a relative repo key to contain at least one Normal path component. A path that is only `.`/`./` (or otherwise empty after expansion) would resolve to the project root itself, which is not a valid checkout directory. This ensures every relative repo entry names a real subdirectory inside the project.

Solutions

  1. Replace the key with the intended subdirectory, e.g. `"dotfiles"` or `"./vendor/lib"`
  2. If the checkout should be the project root, use an absolute path or `~/` path key instead
  3. Remove the entry if it was a placeholder

Example fix

// before
[bootstrap.repos]
"." = { url = "https://github.com/jdx/dotfiles.git" }
// after
[bootstrap.repos]
"dotfiles" = { url = "https://github.com/jdx/dotfiles.git" }
Defensive patterns

Strategy: validation

Validate before calling

fn names_a_directory(p: &str) -> bool {
    std::path::Path::new(p).components().any(|c| matches!(c, std::path::Component::Normal(_)))
}
// assert!(names_a_directory("dotfiles"))

Prevention

When it happens

Trigger: Setting a bootstrap repo key to `"."`, `"./"`, or `""`-equivalent relative forms in a project config so that replace_path yields no Normal components.

Common situations: Trying to bootstrap the project root itself as a repo; accidentally leaving a placeholder `.` key when editing mise.toml; copy/paste that dropped the subdirectory part of the path.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/ecdafba77751450d. Report an issue: GitHub.

Appendix: source

Thrown at src/system/repos.rs:108

                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);
                }
            }
            resolved
        };
        let Some(url) = config.url.map(|s| s.trim().to_string()) else {
            bail!("must set `url`");
        };
        if url.is_empty() {

View on GitHub (pinned to 533346cc37)