{"record":{"id":"6ea2d21c1781ed64","repo":"jdx/mise","slug":"local-plugin-source-cannot-contain-be-or-be-insi","errorCode":null,"errorMessage":"local plugin source cannot contain, be, or be inside the plugin install path: {}","messagePattern":"local plugin source cannot contain, be, or be inside the plugin install path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/plugins/mod.rs","lineNumber":576,"sourceCode":"    if !source.is_dir() {\n        bail!(\n            \"local plugin source is not a directory: {}\",\n            display_path(source)\n        );\n    }\n    let resolved_source = file::desymlink_path(source);\n    let resolved_plugin_path = match (plugin_path.parent(), plugin_path.file_name()) {\n        (Some(parent), Some(file_name)) => file::desymlink_path(parent).join(file_name),\n        _ => plugin_path.to_path_buf(),\n    };\n    if resolved_source\n        .ancestors()\n        .any(|path| file::paths_eq(path, &resolved_plugin_path))\n        || resolved_plugin_path\n            .ancestors()\n            .any(|path| file::paths_eq(path, &resolved_source))\n    {\n        bail!(\n            \"local plugin source cannot contain, be, or be inside the plugin install path: {}\",\n            display_path(source)\n        );\n    }\n    Ok(())\n}\n\npub(crate) fn install_local_plugin_source(\n    plugin_path: &Path,\n    source: &Path,\n    pr: &dyn SingleReport,\n) -> Result<()> {\n    let parent = plugin_path.parent().ok_or_else(|| {\n        eyre!(\n            \"plugin install path has no parent: {}\",\n            display_path(plugin_path)\n        )\n    })?;","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/plugins/mod.rs#L558-L594","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Move the plugin source outside mise's plugin install directory (e.g. ~/src/my-plugin) and install from there.","Point the source at the specific plugin directory rather than a parent that contains the install path.","Inspect symlinks with ls -la / readlink -f, since the check runs on desymlinked paths; restructure so the resolved paths don't overlap."],"exampleFix":"// before\nmise plugin install my-plugin ~/.local/share/mise/plugins  # source contains install path\n// after\nmise plugin install my-plugin ~/src/my-plugin","handlingStrategy":"validation","validationCode":"import std::path::{Path, PathBuf};\nfn paths_overlap(a: &Path, b: &Path) -> bool {\n    let a = a.canonicalize().unwrap_or_else(|_| a.to_path_buf());\n    let b = b.canonicalize().unwrap_or_else(|_| b.to_path_buf());\n    a.starts_with(&b) || b.starts_with(&a)\n}","typeGuard":null,"tryCatchPattern":"match install_local_plugin(name, src) {\n    Err(e) if e.to_string().contains(\"cannot contain, be, or be inside\") => {\n        eprintln!(\"move the plugin source outside the mise plugin install directory\");\n    }\n    r => r,\n}","preventionTips":["Keep local plugin development sources in a directory outside mise's data dir (~/.local/share/mise/plugins).","Point the source at the specific plugin directory, not a broad parent directory.","Resolve symlinks before installing to know what paths mise will compare."],"tags":["filesystem","plugins","validation","paths"],"backgroundTag":"invalid-argument-value","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}