gitbutlerapp/gitbutler · error

The path is not a directory

Error message

The path {} is not a directory

What it means

Thrown when `AddProjectOutcome::NotADirectory` is returned during project registration in `but setup`. The path exists on disk but is a regular file, not a directory, so GitButler cannot treat it as a repository location.

Solutions

  1. Check the target with `ls -la <path>`; confirm it is a directory.
  2. Point setup at the repository root directory, not a file inside it.
  3. If a symlink is involved, ensure it resolves to a directory.

Example fix

// before
but setup ~/projects/myrepo/README.md
// after
but setup ~/projects/myrepo
Defensive patterns

Strategy: validation

Validate before calling

if (!fs.statSync(repoPath).isDirectory()) {
  throw new Error(`${repoPath} is not a directory`);
}

Type guard

function isDirectory(p: string): boolean {
  try { return fs.statSync(p).isDirectory(); } catch { return false; }
}

Try / catch

try {
  await run(['but', 'setup', repoPath]);
} catch (e) {
  if (String(e).includes('is not a directory')) {
    console.error('Pass the repository root directory, not a file.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the setup/add-project flow with a path that resolves to a file (e.g. a tracked file inside the repo, a tarball, or a symlink to a file) instead of a directory containing `.git`.

Common situations: Passing a file path by mistake (autocomplete picking a file); pointing at `myrepo.git` archive file; scripts interpolating wrong variables into the path.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/32b5b9cab5b2234a. Report an issue: GitHub.

Appendix: source

Thrown at crates/but/src/command/legacy/setup.rs:257

                )?;
            }
            Ok(ProjectStatus::Added)
        }
        gitbutler_project::AddProjectOutcome::AlreadyExists(_) => {
            if let Some(out) = out.for_human() {
                writeln!(
                    out,
                    "  {}",
                    t.success.paint("✓ Repository already in project registry")
                )?;
            }
            Ok(ProjectStatus::AlreadyExists)
        }
        gitbutler_project::AddProjectOutcome::PathNotFound => Err(anyhow::anyhow!(
            "The path {} does not exist",
            repo_path.display()
        )),
        gitbutler_project::AddProjectOutcome::NotADirectory => Err(anyhow::anyhow!(
            "The path {} is not a directory",
            repo_path.display()
        )),
        gitbutler_project::AddProjectOutcome::BareRepository => Err(anyhow::anyhow!(
            "The repository at {} is bare. GitButler requires a non-bare repository.",
            repo_path.display()
        )),
        gitbutler_project::AddProjectOutcome::NonMainWorktree => Err(anyhow::anyhow!(
            "The repository at {} is a non-main worktree. GitButler requires the main worktree.",
            repo_path.display()
        )),
        gitbutler_project::AddProjectOutcome::NoWorkdir => Err(anyhow::anyhow!(
            "The repository at {} has no working directory. GitButler requires a working directory.",
            repo_path.display()
        )),
        gitbutler_project::AddProjectOutcome::NoDotGitDirectory => Err(anyhow::anyhow!(
            "The repository at {} has no .git directory. GitButler requires a .git directory.",
            repo_path.display()

View on GitHub (pinned to 58e5313667)