jdx/mise · error

path must be a non-empty relative path

Error message

path must be a non-empty relative path

What it means

ensure_safe_relative rejects output/manifest paths whose os-string is empty or that are absolute (path.is_absolute()). Cache roots must be relative so they can be joined onto the task root and staged safely; an absolute or empty path breaks that invariant.

Source

Thrown at src/task/task_cache.rs:1254

        } else {
            PathBuf::from(&output)
        };
        ensure_safe_relative(&path).wrap_err_with(|| {
            format!(
                "task {} cache output must stay within {}: {output}",
                task.name,
                root.display()
            )
        })?;
    }
    build_output_matcher(root, &patterns)
        .wrap_err_with(|| format!("task {} has an invalid cache output pattern", task.name))?;
    Ok(())
}

fn ensure_safe_relative(path: &Path) -> Result<()> {
    if path.as_os_str().is_empty() || path.is_absolute() {
        bail!("path must be a non-empty relative path");
    }
    if path.components().any(|c| {
        matches!(
            c,
            Component::ParentDir | Component::RootDir | Component::Prefix(_)
        )
    }) {
        bail!("path must not escape the task directory");
    }
    if !path.components().any(|c| matches!(c, Component::Normal(_))) {
        bail!("path must identify an output beneath the task directory");
    }
    Ok(())
}

fn resolve_output_roots(task: &Task, root: &Path, require_matches: bool) -> Result<Vec<PathBuf>> {
    let mut resolved = BTreeSet::new();
    let patterns = task.outputs.patterns();

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Make the output a relative path under the task/project root: 'dist' not '/dist'
  2. Give templated variables a sane relative default or fail the template when unset
  3. For files outside the project, copy or symlink them into the project before caching

Example fix

# before
outputs = ["{{env.OUT_DIR}}/app.bin"]  # OUT_DIR unset/absolute

# after
outputs = ["dist/app.bin"]
Defensive patterns

Strategy: validation

Validate before calling

python3 - <<'EOF'
import tomllib, sys, os
cfg = tomllib.load(open('mise.toml','rb'))
for name, t in cfg.get('tasks', {}).items():
    for o in map(str, t.get('outputs', [])):
        p = o.lstrip('\\').lstrip('!')
        if not p or os.path.isabs(p):
            sys.exit(f'{name}: output must be non-empty and relative: {o!r}')
print('ok')
EOF

Prevention

When it happens

Trigger: outputs containing "/dist", "C:\\out", an absolute path that survived templating, or an empty string (e.g. from '{{env.OUT_DIR}}' with the variable unset); the check also runs on manifest roots during restore via ensure_safe_relative(root).

Common situations: Templated output paths with missing environment variables rendering to ""; Windows-style absolute paths; users trying to cache files outside the project by specifying an absolute path.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/7a6d41a451c2b895. Report an issue: GitHub.