GitoxideLabs/gitoxide · error

Refusing to checkout index into existing directory

Error message

Refusing to checkout index into existing directory '{}' - remove it and try again

What it means

Thrown by gitoxide-core's exclusive index checkout (`index::checkout_exclusive`) when the destination directory already exists on disk. This command is meant to create the destination itself, so it refuses to overwrite or merge into pre-existing content to avoid clobbering user data.

Solutions

  1. Delete or move the existing destination directory, then re-run the checkout
  2. Choose a fresh destination directory path
  3. In scripts, `rm -rf` the target (carefully) before invoking the checkout
  4. Check `dest.exists()` in the caller and pick a unique path

Example fix

// before
gix repo checkout-exclusive --destination ./worktree
// after
rm -rf ./worktree
gix repo checkout-exclusive --destination ./worktree
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
fn prepare_dest(dest: &Path) -> std::io::Result<()> {
    if dest.exists() {
        std::fs::remove_dir_all(dest)?; // or bail in the caller
    }
    Ok(())
}

Try / catch

match index::checkout_exclusive::checkout(/* args */) {
    Ok(()) => /* proceed */,
    Err(e) if e.to_string().contains("Refusing to checkout index into existing directory") => {
        std::fs::remove_dir_all(dest)?;
        // retry once
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `gix repo checkout-exclusive` (or the `checkout_exclusive` function) with a `dest_directory` path that already exists on the filesystem, even if the directory is empty.

Common situations: Re-running a failed checkout without cleaning up; pointing at a directory created by a previous run or by another tool; scripting where the target path is reused between runs.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/7bd4b74181d28141. Report an issue: GitHub.

Appendix: source

Thrown at gitoxide-core/src/index/checkout.rs:32

pub fn checkout_exclusive(
    index_path: impl AsRef<Path>,
    dest_directory: impl AsRef<Path>,
    repo: Option<PathBuf>,
    mut err: impl std::io::Write,
    mut progress: impl NestedProgress,
    should_interrupt: &AtomicBool,
    index::checkout_exclusive::Options {
        index: Options { object_hash, .. },
        empty_files,
        keep_going,
        thread_limit,
    }: index::checkout_exclusive::Options,
) -> anyhow::Result<()> {
    let repo = repo.map(gix::discover).transpose()?;

    let dest_directory = dest_directory.as_ref();
    if dest_directory.exists() {
        bail!(
            "Refusing to checkout index into existing directory '{}' - remove it and try again",
            dest_directory.display()
        )
    }
    std::fs::create_dir_all(dest_directory)?;

    let mut index = parse_file(index_path, object_hash)?;

    let mut num_skipped = 0;
    let maybe_symlink_mode = if !empty_files && repo.is_some() {
        gix::index::entry::Mode::DIR
    } else {
        gix::index::entry::Mode::SYMLINK
    };
    for entry in index.entries_mut().iter_mut().filter(|e| {
        e.mode
            .contains(maybe_symlink_mode | gix::index::entry::Mode::DIR | gix::index::entry::Mode::COMMIT)
    }) {

View on GitHub (pinned to e73179060b)