{"record":{"id":"ec86f43eb76d47e5","repo":"ansible/ansible","slug":"s-is-not-a-directory-ec86f4","errorCode":null,"errorMessage":"%s is not a directory","messagePattern":"(.+?) is not a directory","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/ansible/modules/git.py","lineNumber":851,"sourceCode":"    else:\n        repo_path = os.path.join(dest, '.git')\n    # 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\n    # submodule structure).\n    if os.path.isfile(repo_path):\n        with open(repo_path, 'r') as gitfile:\n            data = gitfile.read()\n        ref_prefix, gitdir = data.rstrip().split('gitdir: ', 1)\n        if ref_prefix:\n            raise ValueError('.git file has invalid git dir reference format')\n\n        # There is a possibility the .git file to have an absolute path.\n        if os.path.isabs(gitdir):\n            repo_path = gitdir\n        else:\n            # Use original destination directory with data from .git file.\n            repo_path = os.path.join(dest, gitdir)\n        if not os.path.isdir(repo_path):\n            raise ValueError('%s is not a directory' % repo_path)\n    return repo_path\n\n\ndef get_head_branch(git_path, module, dest, remote, bare=False):\n    \"\"\"\n    Determine what branch HEAD is associated with.  This is partly\n    taken from lib/ansible/utils/__init__.py.  It finds the correct\n    path to .git/HEAD and reads from that file the branch that HEAD is\n    associated with.  In the case of a detached HEAD, this will look\n    up the branch in .git/refs/remotes/<remote>/HEAD.\n    \"\"\"\n    try:\n        repo_path = get_repo_path(dest, bare)\n    except (OSError, ValueError) as ex:\n        # No repo path found\n        # ``.git`` file does not have a valid format for detached Git dir.\n        module.fail_json(\n            msg='Current repo does not have a valid reference to a '","sourceCodeStart":833,"sourceCodeEnd":869,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/modules/git.py#L833-L869","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (dangling submodule pointer in dest/.git)\n# gitdir: ../.git/modules/mylib   <- directory does not exist\n\n# after: re-init submodule from the superproject\ngit submodule update --init --recursive\n# or re-clone:\nansible.builtin.git:\n  repo: https://example.com/repo.git\n  dest: /srv/checkout\n  force: true","handlingStrategy":"validation","validationCode":"import os\n\ndef gitdir_resolves(dest):\n    \"\"\"True if dest/.git is absent, a dir, or a file whose gitdir: target exists.\"\"\"\n    dotgit = os.path.join(dest, '.git')\n    if not os.path.exists(dotgit):\n        return False\n    if os.path.isdir(dotgit):\n        return True\n    with open(dotgit) as f:\n        data = f.read()\n    _, gitdir = data.rstrip().split('gitdir: ', 1)\n    repo = gitdir if os.path.isabs(gitdir) else os.path.join(dest, gitdir)\n    return os.path.isdir(repo)","typeGuard":null,"tryCatchPattern":"try:\n    repo_path = get_repo_path(dest)\nexcept ValueError as e:\n    fail_json(msg=str(e), hint='Check .git gitdir reference for submodules/worktrees')","preventionTips":["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"],"tags":["git","submodule","filesystem","ansible-module"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}