jdx/mise · error

local plugin source cannot contain, be, or be inside the plu

Error message

local plugin source cannot contain, be, or be inside the plugin install path: {}

What it means

validate_local_plugin_source rejects a local plugin source whose path overlaps the plugin install destination: the source cannot be the install path itself, be inside it, or contain it (checked in both ancestor directions after desymlinking). Installing would otherwise copy/symlink a directory into (or out of) itself, corrupting the install or creating recursive structures.

Source

Thrown at src/plugins/mod.rs:576

    if !source.is_dir() {
        bail!(
            "local plugin source is not a directory: {}",
            display_path(source)
        );
    }
    let resolved_source = file::desymlink_path(source);
    let resolved_plugin_path = match (plugin_path.parent(), plugin_path.file_name()) {
        (Some(parent), Some(file_name)) => file::desymlink_path(parent).join(file_name),
        _ => plugin_path.to_path_buf(),
    };
    if resolved_source
        .ancestors()
        .any(|path| file::paths_eq(path, &resolved_plugin_path))
        || resolved_plugin_path
            .ancestors()
            .any(|path| file::paths_eq(path, &resolved_source))
    {
        bail!(
            "local plugin source cannot contain, be, or be inside the plugin install path: {}",
            display_path(source)
        );
    }
    Ok(())
}

pub(crate) fn install_local_plugin_source(
    plugin_path: &Path,
    source: &Path,
    pr: &dyn SingleReport,
) -> Result<()> {
    let parent = plugin_path.parent().ok_or_else(|| {
        eyre!(
            "plugin install path has no parent: {}",
            display_path(plugin_path)
        )
    })?;

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Move the plugin source outside mise's plugin install directory (e.g. ~/src/my-plugin) and install from there.
  2. Point the source at the specific plugin directory rather than a parent that contains the install path.
  3. Inspect symlinks with ls -la / readlink -f, since the check runs on desymlinked paths; restructure so the resolved paths don't overlap.

Example fix

// before
mise plugin install my-plugin ~/.local/share/mise/plugins  # source contains install path
// after
mise plugin install my-plugin ~/src/my-plugin
Defensive patterns

Strategy: validation

Validate before calling

import std::path::{Path, PathBuf};
fn paths_overlap(a: &Path, b: &Path) -> bool {
    let a = a.canonicalize().unwrap_or_else(|_| a.to_path_buf());
    let b = b.canonicalize().unwrap_or_else(|_| b.to_path_buf());
    a.starts_with(&b) || b.starts_with(&a)
}

Try / catch

match install_local_plugin(name, src) {
    Err(e) if e.to_string().contains("cannot contain, be, or be inside") => {
        eprintln!("move the plugin source outside the mise plugin install directory");
    }
    r => r,
}

Prevention

When it happens

Trigger: `mise plugin install <name> <path>` where the resolved source and the computed install path under mise's plugin directory are equal or ancestor/descendant of one another — e.g. installing a plugin into a directory that lives inside the source tree, or pointing the source at a parent directory that contains mise's plugin install root.

Common situations: Developing a plugin inside ~/.local/share/mise/plugins/<name> itself and trying to install from there; pointing source at a broad parent directory like the whole mise data dir; unusual symlink layouts that make paths resolve into each other.

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/6ea2d21c1781ed64. Report an issue: GitHub.