Hmbown/CodeWhale · error
cannot install a bundle from inside the user plugins…
Error message
cannot install a bundle from inside the user plugins directory {}; it is already in place What it means
`stage_local_copy` refuses to stage a local bundle whose canonical path is inside the user plugins directory — those files are already installed in place, and copying them onto themselves via staging is meaningless/dangerous. The error reports the canonical plugins dir.
Solutions
- Install from the original source location outside the plugins directory
- If the bundle is already installed in place, no install is needed — enable it instead (`/plugin enable <name>`)
- Move the bundle out of the plugins dir first if you truly need to (re)install it
Example fix
// before /plugin install ~/.codewhale/plugins/myplugin // after: install from the project source /plugin install ~/projects/myplugin
Defensive patterns
Strategy: validation
Validate before calling
let canon_source = fs::canonicalize(source_path)?;
let canon_plugins = fs::canonicalize(user_plugins_dir)?;
if canon_source.starts_with(&canon_plugins) {
eprintln!("source is already inside the plugins dir; nothing to install");
return;
} Try / catch
match install(path) {
Err(e) if e.to_string().contains("already in place") => {
eprintln!("bundle already lives in the plugins dir; enable it instead");
}
other => other?,
} Prevention
- Install from project/source directories, never from the plugins dir
- Check the canonicalized path when source locations are configured dynamically
- If already installed, use enable/update instead of reinstall
When it happens
Trigger: Calling `/plugin install <path>` (through `install_inner` → `stage_local_copy`) where `<path>` is inside (or equals) the user plugins directory, e.g. installing a plugin from the very directory it would be installed into.
Common situations: Running install with the plugins dir itself as the source path; installing a subdirectory of the plugins dir; pointing the install source at `~/.codewhale/plugins/...` by mistake.
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
- bundle exceeds the file limit
- installed plugin has no supported manifest
- source is not a valid plugin bundle: no plugin.json…
- staged bundle has no plugin.json…
- The installer did not report the destination path.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ecbbfe8ce9bb6213.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/plugins/install/stage.rs:108
max_size: u64,
) -> Result<StagedPlugin> {
// Validate the source first; this also rejects symlinked roots/manifests.
let manifest_path =
crate::plugins::agent_plugin::resolve_manifest_path(source).ok_or_else(|| {
anyhow::anyhow!(
"source is not a valid plugin bundle: no plugin.json, .claude-plugin/plugin.json, kimi.plugin.json, or plugin.toml"
)
})?;
PluginManifest::validate_from_path(&manifest_path)
.map_err(|error| anyhow::anyhow!("source is not a valid plugin bundle: {error}"))?;
let canonical_source = source
.canonicalize()
.with_context(|| format!("failed to resolve {}", source.display()))?;
if let Ok(canonical_plugins) = user_plugins_dir.canonicalize()
&& (canonical_source == canonical_plugins
|| canonical_source.starts_with(&canonical_plugins))
{
bail!(
"cannot install a bundle from inside the user plugins directory {}; \
it is already in place",
canonical_plugins.display()
);
}
let staged_path = fresh_staging_dir(user_plugins_dir)?;
let result = (|| -> Result<StagedPlugin> {
let mut budget = CopyBudget::default();
copy_bundle_regular_files(&canonical_source, &staged_path, max_size, &mut budget)?;
let (name, content_hash) = validate_staged(&staged_path)?;
Ok(StagedPlugin {
name,
staged_path: staged_path.clone(),
content_hash,
})
})();
if result.is_err() {View on GitHub (pinned to 73e0f67d83)