Hmbown/CodeWhale · error
local install path must not be empty
Error message
local install path must not be empty
What it means
PluginInstallSource::local handles the `path:<dir>` (and fallback) branch of source parsing. It trims the spec and rejects an empty remaining value, because a local plugin install must point at a concrete directory containing the plugin bundle.
Solutions
- Supply the directory after the prefix, e.g. `path:/home/me/plugins/myplugin`
- Fix the unset shell/config variable that emptied the path
- Validate the path is non-empty and exists before calling parse
Example fix
// before source = "path:" // after source = "path:./plugins/my-plugin"
Defensive patterns
Strategy: validation
Validate before calling
fn local_path_spec_ok(spec: &str) -> bool { spec.strip_prefix("path:").map_or(true, |p| !p.trim().is_empty()) } Try / catch
match PluginInstallSource::parse(spec) { Err(e) if e.to_string().contains("local install path must not be empty") => eprintln!("path: prefix requires a directory"), other => other?, } Prevention
- Check path exists and is a directory before install
- Avoid unquoted variable expansion that can empty the path
- Validate `path:` specs at config-load time
When it happens
Trigger: Passing `path:` with nothing after the prefix (e.g. `path:`, `path: `), or falling through to local() with an empty/whitespace string from a config field or unquoted shell variable.
Common situations: Config entry `source = "path:"` with the directory accidentally omitted; `path:$PLUGIN_DIR` where PLUGIN_DIR is empty; copy-paste dropping the actual path.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- install source must not be empty
- base URL cannot be empty
- browser URL cannot be empty
- budget baseline_receipt path changed
- classifier-approved read command was empty
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/161c07e37e0485bf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/plugins/install/mod.rs:136
{
let source = InstallSource::parse(trimmed)?;
return match source {
InstallSource::GitHubRepo(_) | InstallSource::DirectUrl(_) => {
remote_bundle_path(&source)?;
Ok(Self::Remote(source))
}
InstallSource::Registry(_) => {
unreachable!("prefixed specs never parse as a registry name")
}
};
}
Self::local(trimmed)
}
fn local(spec: &str) -> Result<Self> {
let trimmed = spec.trim();
if trimmed.is_empty() {
bail!("local install path must not be empty");
}
Ok(Self::LocalPath(PathBuf::from(trimmed)))
}
}
/// Select one manifest-rooted bundle from a repository archive. The fragment
/// is local extraction metadata, never a path sent to or executed by a server.
fn remote_bundle_path(source: &InstallSource) -> Result<Option<String>> {
let InstallSource::DirectUrl(raw) = source else {
return Ok(None);
};
let url = reqwest::Url::parse(raw).context("invalid plugin archive URL")?;
let Some(fragment) = url.fragment() else {
return Ok(None);
};
let path = fragment
.strip_prefix("path=")
.context("plugin archive fragment must be #path=<bundle-directory>")?;View on GitHub (pinned to 73e0f67d83)