Hmbown/CodeWhale · error
install source must not be empty
Error message
install source must not be empty
What it means
InstallSource::parse rejects an empty or whitespace-only skill install spec before any network or filesystem work. Every non-empty spec routes into the github:/https://registry classification, so this error purely means nothing was passed to install.
Source
Thrown at crates/tui/src/skills/install.rs:118
GitHubRepo(String),
/// Raw `http(s)://…` tarball URL. Used as-is.
DirectUrl(String),
/// Curated registry lookup key. Looked up via the configured `registry_url`.
Registry(String),
}
impl InstallSource {
/// Parse a user-supplied spec. Empty / whitespace-only input is rejected.
///
/// * `github:owner/repo` → [`InstallSource::GitHubRepo`]
/// * `https://github.com/owner/repo[.git]` (no path past the repo) →
/// [`InstallSource::GitHubRepo`]
/// * any other `http://` or `https://` prefix → [`InstallSource::DirectUrl`]
/// * anything else → [`InstallSource::Registry`]
pub fn parse(spec: &str) -> Result<Self> {
let trimmed = spec.trim();
if trimmed.is_empty() {
bail!("install source must not be empty");
}
if let Some(rest) = trimmed.strip_prefix("github:") {
let rest = rest.trim();
// Reject obviously bogus values up front. We intentionally accept
// case-insensitive owner/repo so `github:Hmbown/Foo` works.
let (owner, repo) = rest.split_once('/').with_context(|| {
format!("github source must be 'github:owner/repo' (got {spec})")
})?;
let owner = owner.trim();
let repo = repo.trim().trim_end_matches('/');
if owner.is_empty() || repo.is_empty() {
bail!("github source must be 'github:owner/repo' (got {spec})");
}
if owner.contains('/') || repo.contains('/') {
bail!("github source must be 'github:owner/repo' (got {spec})");
}
return Ok(Self::GitHubRepo(format!("{owner}/{repo}")));
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Pass a real spec: 'github:owner/repo', an https URL, or a registry name.
- If a wrapper builds the spec from variables, assert it is non-empty before invoking install.
- Quote arguments so unbound variables do not collapse to empty strings.
- Treat as a pure input error: nothing was fetched, no cleanup is needed.
Example fix
# before /skill install "" # after /skill install github:owner/repo
Defensive patterns
Strategy: validation
Validate before calling
let spec = spec.trim();
if spec.is_empty() {
eprintln!("skill spec is required: github:owner/repo, https URL, or registry name");
return;
} Prevention
- Make wrappers fail fast on empty or unset spec variables instead of forwarding them.
- Quote arguments so shell splitting cannot silently drop them.
- Treat this error as a no-op: nothing was fetched or written.
When it happens
Trigger: Invoking the skill install flow with an empty argument: '/skill install' with no spec, a spec of only spaces, or a wrapper passing an unset environment variable as the spec.
Common situations: Argument-parsing bugs in wrappers, empty-string defaults ('${SKILL_SPEC:-}'), copy-paste that lost the spec, and UI flows submitting before input.
Related errors
- github source must be 'github:owner/repo' (got {spec})
- continual harness entry id cannot be empty
- DSH plugin path not available: {reason}
- Failed to parse boolean '{value}': expected on/off, true/fal
- skill '{name}' was imported locally (spec '{}') and cannot b
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/0ea02840a46a743c.
Report an issue: GitHub.