Git "destination path already exists and is not an empty directory"
By Daniel Zoghalchali·Latchkey
Git refuses to clone into a directory that already has files in it. On a reused or self-hosted runner the previous job left a checkout behind, so the fresh clone has nowhere clean to land.
What this error means
A git clone step fails immediately with fatal: destination path 'repo' already exists and is not an empty directory. It happens on persistent/self-hosted runners that reuse the same workspace, not on ephemeral runners that start clean.
git clone output
fatal: destination path 'app' already exists and is not an empty directory.
Diagnose it: depth, refs, or credentials?
CI checkouts are shallow and detached by default, which breaks anything that needs history or a branch name. Before treating it as a credential problem, confirm what the runner actually fetched.
.github/workflows/ci.yml
- run:|git rev-parse --is-shallow-repositorygit rev-parse --abbrev-ref HEAD # prints HEAD when detachedgit log --oneline -3git remote -vgit for-each-ref --format="%(refname)" | head
Common causes
A leftover checkout from a previous job
Self-hosted or reused runners keep the working directory between jobs. A prior clone is still there, so the new clone target is non-empty and Git aborts.
A cache or artifact restored into the clone path
A cache restore or artifact download placed files at the same path the clone targets, leaving the directory dirty before the clone runs.
How to fix it
Clean the workspace before cloning
Remove or empty the target directory at the start of the job so the clone has a clean landing spot.
- uses:actions/checkout@v4with:fetch-depth:0 # full history: diffs, tags, git describesubmodules:recursive # submodules are NOT fetched by defaultpersist-credentials:false # if a later step pushes with its own token
How to prevent it
Use ephemeral runners, or clean the workspace at job start on persistent ones.
Enable actions/checkout’s clean step (default) so the workspace resets each run.
Avoid restoring caches/artifacts into the repository checkout path.
Frequently asked questions
What causes Git "destination path already exists and is not an empty directory"?
There are 2 common causes: a leftover checkout from a previous job and a cache or artifact restored into the clone path. Self-hosted or reused runners keep the working directory between jobs.
How do I fix Git "destination path already exists and is not an empty directory"?
There are 2 fixes depending on which cause you have: clean the workspace before cloning and reset an existing checkout instead of re-cloning. Work through them in order, since the first is the most common.
What does Git "destination path already exists and is not an empty directory" actually mean?
A git clone step fails immediately with fatal: destination path 'repo' already exists and is not an empty directory.
How do I stop Git "destination path already exists and is not an empty directory" happening again?
Use ephemeral runners, or clean the workspace at job start on persistent ones. The prevention section lists 3 changes that keep it from recurring.