gitbutlerapp/gitbutler · error
The repository at {} uses the currently unsupported reftable
Error message
The repository at {} uses the currently unsupported reftable reference format. What it means
Raised while registering a repository: the repo uses git's reftable reference storage backend (`AddProjectOutcome::ReftableRefFormatUnsupported`), which the gix-based stack GitButler builds on does not yet support. Only the classic 'files' ref backend (loose refs + packed-refs) is accepted.
Source
Thrown at crates/but/src/command/legacy/setup.rs:258
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()
)),
gitbutler_project::AddProjectOutcome::ReftableRefFormatUnsupported => Err(anyhow::anyhow!(
"The repository at {} uses the currently unsupported reftable reference format.",
repo_path.display()
)),
gitbutler_project::AddProjectOutcome::NotAGitRepository(_) => Err(anyhow::anyhow!(
"The path {} is not a git repository.",
repo_path.display()
)),
}?;
// A ported project can keep its target in Git config while the legacy `virtual_branches.toml`
// / database store is empty — for example after that store was reset. The check below would
// then see a target and report "already set up", but the workspace needs the legacy default
// target to work. Repair it from the workspace first so setup isn't a dead end.
if gitbutler_branch_actions::base::bootstrap_default_target_if_missing(&*ctx)?
&& let Some(out) = out.for_human()
{
writeln!(
out,View on GitHub (pinned to caf1f223d3)
Solutions
- Re-clone the repository with the files backend: `git clone --ref-format=files <url>` and register the new clone
- Check and unset the global opt-in so future repos work: `git config --global --get init.defaultRefFormat`, then `git config --global --unset init.defaultRefFormat`
- For a brand-new local repo: delete it and `git init --ref-format=files` again (there is no supported reftable-to-files downgrade)
- Track GitButler/gix releases for reftable support instead of working around it in place
Example fix
# before: reftable repo rejected but setup ~/work/project # after: fresh clone on the files backend git clone --ref-format=files git@example.com:project.git ~/work/project-fresh but setup ~/work/project-fresh
Defensive patterns
Strategy: validation
Validate before calling
let fmt = std::process::Command::new("git")
.args(["-C", repo_path.to_str().unwrap(), "config", "--get", "extensions.refformat"])
.output()?;
if String::from_utf8_lossy(&fmt.stdout).trim() == "reftable" {
anyhow::bail!("repo uses reftable refs, which is unsupported; re-clone with --ref-format=files");
} Type guard
fn is_reftable(out: &gitbutler_project::AddProjectOutcome) -> bool {
matches!(out, gitbutler_project::AddProjectOutcome::ReftableRefFormatUnsupported)
} Try / catch
match add_project(&repo_path) {
Ok(out) if is_reftable(&out) => { /* re-clone with --ref-format=files */ }
Ok(out) => { /* other outcomes */ }
Err(err) if err.to_string().contains("reftable") => { /* reftable guidance */ }
Err(err) => return Err(err),
} Prevention
- Keep `init.defaultRefFormat` unset (files backend) on machines that also run GitButler tooling
- When cloning from reftable experiments, pass `--ref-format=files` explicitly
- There is no in-place downgrade; plan a re-clone instead of debugging the rejection
When it happens
Trigger: Setup against a repository created or migrated with `git init --ref-format=reftable`, or cloned from a reftable upstream; typically after opting in globally via `git config --global init.defaultRefFormat reftable` or the `extensions.refformat=reftable` config.
Common situations: Early adopters of the experimental reftable backend (git >= 2.45); machines where another tool or tutorial enabled reftable by default; repos shared from a reftable-configured workstation.
Related errors
- The repository at {} is bare. GitButler requires a non-bare
- The repository at {} is a non-main worktree. GitButler requi
- The repository at {} has no working directory. GitButler req
- The repository at {} has no .git directory. GitButler requir
- The path {} is not a git repository.
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/9da3aabd6652a30d.
Report an issue: GitHub.