gitbutlerapp/gitbutler · error
GitButler project data does not exist at
Error message
GitButler project data does not exist at '{}' What it means
repo-installer dump locates the GitButler project data directory via repo.gitbutler_storage_path() and requires it to exist as a directory. If the path doesn't exist (or isn't a directory) the dump cannot proceed, so it fails with this ensure! message including the path.
Solutions
- Open the repository in GitButler first so project data is created, then re-run the dump.
- Verify the printed path exists: check `.git/gitbutler/` inside the repo.
- Restore the deleted storage directory from backup or re-add the project to regenerate it.
Example fix
// before $ git clone x && but-debug dump repo-installer # no GitButler data yet // after $ gitbutler add-project ./x # creates project data $ but-debug dump repo-installer
Defensive patterns
Strategy: validation
Validate before calling
if [ ! -d .git/gitbutler ]; then echo 'No GitButler project data; open the project in GitButler first'; exit 1; fi
Type guard
fn has_project_data(repo: &gix::Repository) -> bool {
repo.gitbutler_storage_path().map(|p| p.is_dir()).unwrap_or(false)
} Prevention
- Open the repo in GitButler at least once before dumping.
- Check the printed storage path exists before running the command.
- Don't delete .git/gitbutler manually.
When it happens
Trigger: Running `but-debug dump repo-installer` in a repository that has never been opened/managed by GitButler, so no .git/gitbutler (project storage) directory exists.
Common situations: Fresh clones dumped before ever opening the project in GitButler; storage directory deleted manually; running against a repo from a different machine's layout.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Aborting due to empty branch name
- Ad-hoc (single-branch) branch moves are not supported…
- An octopus merge commits must have at least two parents
- another pre-commit hook is already using the repository…
- askpass broker must be initialized
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/7f67c7aef240311c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-debug/src/command/dump/repo_installer.rs:47
let repo = setup::repo_from_args(args).with_context(|| {
format!(
"Could not discover Git repository at '{}'",
current_dir.display()
)
})?;
let repo = gix::open_opts(repo.git_dir().canonicalize()?, repo.open_options().clone())?;
let workdir = repo
.workdir()
.context("Repository installers require a non-bare repository")?;
ensure!(
repo.git_dir() == repo.common_dir(),
"Repository installers require the main worktree"
);
let project_data_dir = repo
.gitbutler_storage_path()
.context("Could not locate GitButler project data")?;
ensure!(
project_data_dir.is_dir(),
"GitButler project data does not exist at '{}'",
project_data_dir.display()
);
let base = archive_base_name(&repo)?;
let archive_root = format!("{base}-repo-installer");
let output_path = match &installer_args.archive.output {
Some(path) => current_dir.join(path),
None => default_output_path(&repo, "repo-installer")?,
};
let output_path = OutputPath::new(output_path, current_dir);
let archive_lock = acquire_archive_lock(&output_path.path, Some(workdir.to_owned()))?;
let output_path = output_path.with_lock_path(archive_lock.lock_path().to_owned());
let _repo_guard =
but_core::sync::exclusive_repo_access(repo.git_dir(), Some(&project_data_dir));
let clone_remote = clone_remote(&repo, workdir)?;View on GitHub (pinned to 58e5313667)