gitbutlerapp/gitbutler · error
Could not detect an existing GitButler skill installation. R
Error message
Could not detect an existing GitButler skill installation. Run `but skill install` to create one, or use `--path <dir>` to choose a location.
What it means
detect_install_paths backs the --detect flag of `but skill update`/`but skill status`: it collects installation paths from the local (repo) scope and the global scope, in that priority. If neither scope contains a GitButler skill installation, there is nothing to detect or update and the command bails with instructions to install or pass --path.
Source
Thrown at crates/but/src/command/skill/mod.rs:832
/// Returns every GitButler skill in the highest-priority scope that has one
/// (local before global), so `--detect` refreshes them all instead of forcing a
/// choice between them. Filtering to a single scope keeps a repo-local `--detect`
/// from reaching into global installs.
fn detect_install_paths(ctx: Option<&mut Context>, global: bool) -> Result<Vec<PathBuf>> {
let installations = find_all_installations(ctx, true, !global)?;
for scope in [SCOPE_LOCAL, SCOPE_GLOBAL] {
let paths: Vec<PathBuf> = installations
.iter()
.filter(|(_, _, s)| *s == scope)
.map(|(path, _, _)| path.clone())
.collect();
if !paths.is_empty() {
return Ok(paths);
}
}
anyhow::bail!(
"Could not detect an existing GitButler skill installation.\n\
Run `but skill install` to create one, or use `--path <dir>` to choose a location."
)
}
fn prompt_for_install_scope(
input: &mut crate::utils::InputOutputChannel<'_>,
progress: &mut impl std::io::Write,
) -> Result<InstallScope> {
let t = theme::get();
writeln!(progress)?;
writeln!(
progress,
"{}",
t.important.paint("Select installation scope:")
)?;
writeln!(progress)?;
View on GitHub (pinned to caf1f223d3)
Solutions
- Run `but skill install` to create an installation first, then retry --detect
- Pass `--path <dir>` pointing at the existing moved/renamed installation
- Reinstall at the default location so future `--detect` updates work
Example fix
$ but skill update --detect # fails: nothing installed $ but skill install # create one $ but skill update --detect # now succeeds
Defensive patterns
Strategy: validation
Validate before calling
// verify an installation exists before `update --detect`
let installed = [".claude/skills/gitbutler", /* global path */]
.iter()
.any(|p| std::path::Path::new(p).join("SKILL.md").exists());
if !installed { /* run `but skill install` instead of `update --detect` */ } Prevention
- Run `but skill install` before scripting `but skill update --detect`
- Keep the skill at the default path so --detect finds it
- Pin --path in automation to avoid detection entirely
When it happens
Trigger: Calling `but skill update --detect` before `but skill install` was ever run, or after the skill directory (e.g. .claude/skills/gitbutler or the global equivalent) was deleted or moved to a non-default location.
Common situations: Fresh machine where the skill was never installed, cleanup scripts that wiped dotfile directories, installations renamed so detection scans miss them.
Related errors
- No supported agent was detected. In non-interactive mode, sp
- Human input required - run this in a terminal, or specify --
- Cannot use both --detect and --path options together
- Installation path {} is a file, not a directory. Please spec
- Refusing to install symlink onto existing non-symlink at '{U
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/b69acd18092fde35.
Report an issue: GitHub.