gitbutlerapp/gitbutler · error

Repository has no working directory

Error message

Repository has no working directory

What it means

Thrown by `setup_local_remote` when no push remote is configured anywhere, so setup tries to fabricate a `gb-local` remote pointing at the repository itself. The remote URL is derived from `repo.workdir()`; on a bare repository (or a repo opened without a worktree) `workdir()` is None and this error is returned before any config is written.

Source

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

    if ws.remote_name().is_none()
        && repo
            .remote_default_name(gix::remote::Direction::Push)
            .is_none()
    {
        anyhow::bail!(
            "Neither found push remote found in workspace nor unambiguously in the Git repository configuration."
        )
    };

    Ok(true)
}

/// Creates a 'gb-local' remote pointing to this repository and creates tracking refs for the default branch.
fn setup_local_remote(repo: &gix::Repository, out: &mut OutputChannel) -> anyhow::Result<String> {
    let t = theme::get();
    let repo_url = repo
        .workdir()
        .ok_or_else(|| anyhow::anyhow!("Repository has no working directory"))?
        .to_str()
        .ok_or_else(|| anyhow::anyhow!("Repository path is not valid UTF-8"))?;

    if let Some(out) = out.for_human() {
        writeln!(
            out,
            "  {}",
            t.info
                .paint("No push remote found, creating gb-local remote...")
        )?;
    }

    edit_repo_config(repo, gix::config::Source::Local, |config| {
        let mut section = config.section_mut_or_create_new("remote", Some("gb-local".into()))?;
        section.push("url", repo_url)?;
        Ok(())
    })?;

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Run setup from a non-bare working clone of the repository instead
  2. Configure a real push remote before setup so the gb-local fallback is never needed: `git remote add origin <url> && git push -u origin HEAD`
  3. If you must work where you are, create a worktree-style clone next to the bare repo and register that

Example fix

# before: bare repo, no push remote
cd /srv/git/project.git && but setup

# after: give it a remote to use
git -C /srv/git/project.git remote add origin git@example.com:project.git
but setup /srv/git/project.git
Defensive patterns

Strategy: validation

Validate before calling

let repo = gix::open(&repo_path)?;
let Some(workdir) = repo.workdir() else {
    anyhow::bail!("no working directory; configure a push remote or use a non-bare clone");
};
if workdir.to_str().is_none() {
    anyhow::bail!("workdir path is not valid UTF-8; move the repo");
}

Try / catch

match setup_local_remote(&repo, &mut out) {
    Ok(remote) => { /* use remote */ }
    Err(err) if err.to_string().contains("no working directory") => {
        // add a real push remote instead of the gb-local fallback
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Running `but setup` in a bare repository (or worktree-less core) that also has no push remote configured in the workspace or git config — the gb-local fallback path is taken and immediately fails on the missing workdir.

Common situations: Setting up tooling inside a bare central repo on a server; CI jobs that check out with unusual git dir layouts; a workspace config that lost its remote entries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/8e3f82b058dcce8a. Report an issue: GitHub.