jdx/mise · error

tracking requires a portable path under home or the mise con

Error message

tracking requires a portable path under home or the mise configuration directory

What it means

Before tracking a path, ensure_portable_ancestors checks that the requested path is relative to either the user's home directory or the mise configuration directory, so tracking metadata can be stored portably. If the path is not under either base (or cannot be made relative to them), tracking is refused.

Source

Thrown at src/system/history/tracked.rs:827

            let actual = components.next()?;
            if actual != expected
                && !(cfg!(windows)
                    && actual
                        .as_os_str()
                        .to_string_lossy()
                        .eq_ignore_ascii_case(&expected.as_os_str().to_string_lossy()))
            {
                return None;
            }
        }
        Some(components.collect::<PathBuf>())
    };
    let Some((base, rest)) = bases
        .iter()
        .filter_map(|base| relative(base).map(|rest| (base, rest)))
        .max_by_key(|(base, _)| base.components().count())
    else {
        eyre::bail!(
            "tracking requires a portable path under home or the mise configuration directory"
        );
    };
    let mut ancestor = base.clone();
    for component in rest
        .components()
        .take(rest.components().count().saturating_sub(1))
    {
        ancestor.push(component);
        if file::is_symlink_or_junction(&ancestor) {
            eyre::bail!(
                "cannot track {} through symlinked parent {}; explicitly track the link itself and its real target instead",
                display_path(path),
                display_path(&ancestor)
            );
        }
    }
    Ok(())

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Track the file via a path under your home directory (e.g. a symlink or bind mount inside $HOME pointing to it, or move the file into home).
  2. Set MISE_CONFIG_DIR (or the equivalent config dir setting) so the parent directory of the target falls under the mise configuration directory.
  3. Copy or move the file into a location under home or the config dir and track that copy.
  4. If the file must stay put, use a different mechanism (task hooks, direnv) since tracking is intentionally limited to portable roots.

Example fix

// before
mise history track /opt/shared/toolchain.json   // outside home and config dir
// after
mkdir -p ~/shared && ln -s /opt/shared/toolchain.json ~/shared/toolchain.json
mise history track ~/shared/toolchain.json
Defensive patterns

Strategy: validation

Validate before calling

// before tracking, verify the path is under home or the mise config dir
use std::path::{Path, PathBuf};
fn is_portable(path: &Path, home: &Path, config_dir: &Path) -> bool {
    path.starts_with(home) || path.starts_with(config_dir)
}

Try / catch

match result {
    Err(e) if e.to_string().contains("portable path under home") => {
        eprintln!("track files only under $HOME or MISE_CONFIG_DIR");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling add_requests (history track/track-file style API) with an absolute path outside home and the mise config dir, e.g. `/opt/tools/foo`, `/tmp/foo`, or a path on another mount; or passing a relative/unresolvable path that matches none of the configured bases.

Common situations: Trying to track a file in a system location, a temp directory, a Docker volume mount, or a symlink-expanded path that resolves outside home; often after `mise history track /etc/something` or config in a custom root.

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@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/ad4ef14999087411. Report an issue: GitHub.