ansible/ansible · error · ValueError
%s is not a directory
Error message
%s is not a directory
What it means
Raised by AnsibleModule's git module helper (get_repo_path) after parsing a '.git' file that contains a 'gitdir: <path>' pointer. The pointer is resolved either as an absolute path or relative to the destination directory; if the resolved path is not an existing directory, this ValueError fires. It almost always indicates a broken or stale submodule/worktree checkout where the .git file points at a missing .git dir.
Source
Thrown at lib/ansible/modules/git.py:851
else:
repo_path = os.path.join(dest, '.git')
# Check if the .git is a file. If it is a file, it means that the repository is in external directory respective to the working copy (e.g. we are in a
# submodule structure).
if os.path.isfile(repo_path):
with open(repo_path, 'r') as gitfile:
data = gitfile.read()
ref_prefix, gitdir = data.rstrip().split('gitdir: ', 1)
if ref_prefix:
raise ValueError('.git file has invalid git dir reference format')
# There is a possibility the .git file to have an absolute path.
if os.path.isabs(gitdir):
repo_path = gitdir
else:
# Use original destination directory with data from .git file.
repo_path = os.path.join(dest, gitdir)
if not os.path.isdir(repo_path):
raise ValueError('%s is not a directory' % repo_path)
return repo_path
def get_head_branch(git_path, module, dest, remote, bare=False):
"""
Determine what branch HEAD is associated with. This is partly
taken from lib/ansible/utils/__init__.py. It finds the correct
path to .git/HEAD and reads from that file the branch that HEAD is
associated with. In the case of a detached HEAD, this will look
up the branch in .git/refs/remotes/<remote>/HEAD.
"""
try:
repo_path = get_repo_path(dest, bare)
except (OSError, ValueError) as ex:
# No repo path found
# ``.git`` file does not have a valid format for detached Git dir.
module.fail_json(
msg='Current repo does not have a valid reference to a 'View on GitHub (pinned to 9cf16a4aca)
Solutions
- Inspect the .git file inside dest and confirm the path after 'gitdir: ' exists on the managed host
- If it is a submodule, re-run git submodule update --init or use the git module with the correct parent repo dest
- Re-clone the repository (delete dest or set force/version tweaks) so the .git linkage is regenerated
- If the gitdir is legitimately elsewhere, make the reference an absolute path that is valid on the target machine
Example fix
# before (dangling submodule pointer in dest/.git) # gitdir: ../.git/modules/mylib <- directory does not exist # after: re-init submodule from the superproject git submodule update --init --recursive # or re-clone: ansible.builtin.git: repo: https://example.com/repo.git dest: /srv/checkout force: true
Defensive patterns
Strategy: validation
Validate before calling
import os
def gitdir_resolves(dest):
"""True if dest/.git is absent, a dir, or a file whose gitdir: target exists."""
dotgit = os.path.join(dest, '.git')
if not os.path.exists(dotgit):
return False
if os.path.isdir(dotgit):
return True
with open(dotgit) as f:
data = f.read()
_, gitdir = data.rstrip().split('gitdir: ', 1)
repo = gitdir if os.path.isabs(gitdir) else os.path.join(dest, gitdir)
return os.path.isdir(repo) Try / catch
try:
repo_path = get_repo_path(dest)
except ValueError as e:
fail_json(msg=str(e), hint='Check .git gitdir reference for submodules/worktrees') Prevention
- Validate submodule checkouts before running the git module
- Keep .git gitdir references relative and re-clone after moving checkouts
- Avoid partial submodule updates; use update: --init --recursive
When it happens
Trigger: Running the git module with a dest that is a submodule or linked worktree whose .git file references a gitdir (e.g. ../.git/modules/name) that does not exist on disk; a partially cloned/updated repo; a copied/moved checkout where the relative gitdir path no longer resolves.
Common situations: Submodules cloned shallowly or with update=none leaving dangling .git files; manually moving a worktree directory; interrupted git submodule update; NFS/relative path mismatches when dest differs from the original clone location.
Related errors
- argument spec entry contains an invalid key '{0}', valid key
- argument spec for '{0}' did not match expected type {1}: act
- Unable to read the contents of {path!r}.
- LookupPrivilegeName() failed
- Unsupported JsonElement type: {element.ValueKind}
AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15).
Data as JSON: /api/errors/ec86f43eb76d47e5.
Report an issue: GitHub.