jdx/mise · error
local plugin source is not a directory: {}
Error message
local plugin source is not a directory: {} What it means
During local plugin install, mise requires the source to be a directory (a checked-out plugin repo). If the given path exists but is a regular file (or other non-directory), validate_local_plugin_source bails with this error.
Source
Thrown at src/plugins/mod.rs:559
match source {
PluginSource::Git {
url,
git_ref: None,
subdir: None,
} if url == repository => path.is_absolute().then_some(path),
_ => None,
}
}
pub(crate) fn validate_local_plugin_source(source: &Path, plugin_path: &Path) -> Result<()> {
if !source.exists() {
bail!(
"local plugin directory does not exist: {}",
display_path(source)
);
}
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: {}",View on GitHub (pinned to afd2eddd3a)
Solutions
- Pass the plugin directory, not a file — for archives, extract first (mkdir d && tar -xf plugin.tar.gz -C d) and install from d.
- If pointing at a symlink, verify it resolves to a directory (ls -la <path>).
- Re-clone the plugin repository and install from the cloned directory.
Example fix
// before mise plugin install my-plugin ./my-plugin-v1.0.tar.gz // after tar -xf my-plugin-v1.0.tar.gz && mise plugin install my-plugin ./my-plugin
Defensive patterns
Strategy: validation
Validate before calling
import std::path::Path;
fn ensure_directory(p: &Path) -> std::io::Result<()> {
if !p.is_dir() {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("{} is not a directory", p.display())));
}
Ok(())
} Try / catch
match install_local_plugin(name, path) {
Err(e) if e.to_string().contains("is not a directory") => {
eprintln!("extract the archive and pass the extracted directory");
}
r => r,
} Prevention
- Always install from the plugin's repository root directory, never an archive file or single script.
- Extract tarballs/zips before installing local plugins.
- Verify with `test -d <path>` in shell scripts before invoking mise.
When it happens
Trigger: `mise plugin install <name> <path>` where <path> points at a file — e.g. a tarball/zip of the plugin, the plugin's main script, or a symlink resolving to a file — instead of the plugin's directory.
Common situations: Passing a downloaded plugin archive file instead of extracting it; pointing at the plugin's executable script rather than its repo root; a stale symlink whose target was replaced by a file.
Related errors
- local plugin directory does not exist: {}
- local plugin source cannot contain, be, or be inside the plu
- {target_raw}: target must be absolute or start with ~/
- cannot replace task stub directory because {} does not conta
- cannot replace task stub directory because {} is empty
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/4ca01aea4281e963.
Report an issue: GitHub.