Detail Bug Report
https://app.detail.dev/org_5f375fe3-a706-4e9a-a6f7-800f2439b3f6/bugs/bug_50cf379c-4f50-4ec2-94e5-3dc1b7e9f45a
Introduced in #182 by @sachiniyer on Mar 11, 2026
Summary
- Context: The
detect_shell() function in src/commands/completions.rs extracts the shell name from the $SHELL environment variable for auto-detection when no shell argument is provided.
- Bug: When
$SHELL is set but empty (SHELL=""), or contains only a path with trailing slashes, rsplit('/').next() returns an empty string. The resulting error message "unsupported shell: " shows no visible shell name.
- Actual vs. expected: With
SHELL="" (empty string, but variable IS set), the error "unsupported shell: " is shown instead of a clear message indicating the SHELL variable is empty or malformed.
- Impact: Users receive an opaque error message that doesn't identify the root cause, unlike other error paths in this codebase that clearly identify missing/invalid input.
Code with Bug
fn detect_shell() -> Result<String> {
let shell = env::var("SHELL").context("could not detect shell from $SHELL")?;
// $SHELL is e.g. "/bin/zsh" — take the basename
let name = shell.rsplit('/').next().unwrap_or(&shell); // <-- BUG 🔴 can return "" for empty/malformed $SHELL
Ok(name.to_lowercase())
}
Explanation
env::var("SHELL") distinguishes only between unset (Err) and set (Ok), but does not validate that the value is non-empty / well-formed.
- For
SHELL="", "".rsplit('/').next() returns Some(""), which lowercases to "" and propagates into the completions shell parsing, resulting in an error like: unsupported shell: (supported: ...).
- Similarly, values ending in
/ can yield an empty basename and produce the same opaque error.
Codebase Inconsistency
Other code paths validate/trim empty input and trailing slashes (e.g. src/utils/repos.rs checks for empty parts; src/utils/datetime.rs trims; src/utils/git.rs trims trailing slashes), but detect_shell() does not, leading to inconsistent and less-informative error messages.
Recommended Fix
Trim and validate $SHELL before extracting the basename, and explicitly error on empty/unextractable shell names (including after trimming trailing slashes), e.g.:
let shell = shell.trim(); if shell.is_empty() { bail!("$SHELL is empty"); }
let shell = shell.trim_end_matches('/'); ...; if name.is_empty() { bail!("could not extract shell name from $SHELL: {shell}"); }
History
This bug was introduced in commit fd339df.
Detail Bug Report
https://app.detail.dev/org_5f375fe3-a706-4e9a-a6f7-800f2439b3f6/bugs/bug_50cf379c-4f50-4ec2-94e5-3dc1b7e9f45a
Introduced in #182 by @sachiniyer on Mar 11, 2026
Summary
detect_shell()function insrc/commands/completions.rsextracts the shell name from the$SHELLenvironment variable for auto-detection when no shell argument is provided.$SHELLis set but empty (SHELL=""), or contains only a path with trailing slashes,rsplit('/').next()returns an empty string. The resulting error message "unsupported shell: " shows no visible shell name.SHELL=""(empty string, but variable IS set), the error "unsupported shell: " is shown instead of a clear message indicating the SHELL variable is empty or malformed.Code with Bug
Explanation
env::var("SHELL")distinguishes only between unset (Err) and set (Ok), but does not validate that the value is non-empty / well-formed.SHELL="","".rsplit('/').next()returnsSome(""), which lowercases to""and propagates into the completions shell parsing, resulting in an error like:unsupported shell: (supported: ...)./can yield an empty basename and produce the same opaque error.Codebase Inconsistency
Other code paths validate/trim empty input and trailing slashes (e.g.
src/utils/repos.rschecks for empty parts;src/utils/datetime.rstrims;src/utils/git.rstrims trailing slashes), butdetect_shell()does not, leading to inconsistent and less-informative error messages.Recommended Fix
Trim and validate
$SHELLbefore extracting the basename, and explicitly error on empty/unextractable shell names (including after trimming trailing slashes), e.g.:let shell = shell.trim(); if shell.is_empty() { bail!("$SHELL is empty"); }let shell = shell.trim_end_matches('/'); ...; if name.is_empty() { bail!("could not extract shell name from $SHELL: {shell}"); }History
This bug was introduced in commit fd339df.