8000 ansible.builtin.git: 'NoneType' object has no attribute 'startswith' · Issue #87881 · ansible/ansible · GitHub
[go: up one dir, main page]

Skip to content

ansible.builtin.git: 'NoneType' object has no attribute 'startswith' #87881

Open

Description

@timewasted

Summary

ansible.builtin.git with depth and a tag as version clones fine on the first run. On every later run against the same dest, the module crashes with an unhandled AttributeError instead of reporting ok.

Note that this issue was mostly copied from #87879 because that one was closed and I am having the same issue. The issue seems to be caused by 5186cff.

In my case, is_not_a_branch() returns True which means headfile would be <path to .git>/refs/remotes/origin/HEAD, but my refs directory doesn't have a remotes subdirectory, so head_splitter() returns None. I haven't spent a super lot of time trying to track down why the changes in that commit caused this to fail suddenly, but it seems as though they did.

Issue Type

Bug Report

Component Name

git

Ansible Version

$ ansible --version
ansible [core 2.21.6]
  config file = /home/ryan/Ansible/Homelab/ansible.cfg
  configured module search path = ['/home/ryan/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ryan/.local/share/pipx/venvs/ansible/lib/python3.13/site-packages/ansible
  ansible collection location = /home/ryan/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ryan/.local/bin/ansible
  python version = 3.13.5 (main, Aug 10 2026, 12:06:59) [GCC 14.2.0] (/home/ryan/.local/share/pipx/venvs/ansible/bin/python)
  jinja version = 3.1.6
  pyyaml version = 6.0.3 (with libyaml v0.2.5)

Configuration

# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all

OS / Environment

Linux ansible 6.12.115+deb13.1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.115-2 (2026-11-01) x86_64 GNU/Linux

Steps to Reproduce

python3 -m venv /tmp/repro/venv
/tmp/repro/venv/bin/pip install ansible-core==2.21.6

git init --bare --initial-branch=main /tmp/repro/upstream.git
git clone /tmp/repro/upstream.git /tmp/repro/seed
git -C /tmp/repro/seed commit --allow-empty -m one
git -C /tmp/repro/seed tag -a v1 -m v1
git -C /tmp/repro/seed commit --allow-empty -m two
git -C /tmp/repro/seed push origin HEAD:main --tags

/tmp/repro/venv/bin/ansible localhost -m git \
  -a "repo=/tmp/repro/upstream.git dest=/tmp/repro/checkout version=v1 depth=1 force=true"

/tmp/repro/venv/bin/ansible localhost -m git \
  -a "repo=/tmp/repro/upstream.git dest=/tmp/repro/checkout version=v1 depth=1 force=true"

Expected Results

The second call reports SUCCESS with "changed": false and before == after, as ansible-core 2.21.4 does:

localhost | SUCCESS => {
    "after": "13fc42f91aff0ccf316a57149e34ee9069e4b084",
    "before": "13fc42f91aff0ccf316a57149e34ee9069e4b084",
    "changed": false,
    "remote_url_changed": false
}

Actual Results

[ERROR]: Task failed: Module failed: 'NoneType' object has no attribute 'startswith'

  File ".../ansible/modules/git.py", line 1428, in main
    fetch(git_path, module, repo, dest, version, remote, depth, bare, refspec, git_version_used, force=force)
  File ".../ansible/modules/git.py", line 925, in fetch
    currenthead = get_head_branch(git_path, module, dest, remote)
  File ".../ansible/modules/git.py", line 877, in get_head_branch
    if branch.startswith('-'):
       ^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'startswith'

Code of Conduct

  • I agree to follow the Ansible Code of Conduct

Activity

  1. added
    bugThis issue/PR relates to a bug.
    needs_triageNeeds a first human triage before being processed.
    affects_2.21This issue/PR affects Ansible v2.21
    moduleThis issue/PR relates to a module.
    on Nov 5, 2026
  2. ansibot commented on Nov 5, 2026

    @ansibot
    Contributor

    Files identified in the description:

    If these files are incorrect, please update the component name section of the description or use the component bot command.

  3. timewasted commented on Nov 5, 2026

    @timewasted
    Author

    Simply updating the check from if branch.startswith('-'): to if branch is not None and branch.startswith('-'): fixes the issue, but I haven't dug in to see if that has any other effects or if something similar needs to be applied elsewhere.

  4. bunnysayzz commented on Nov 5, 2026

    @bunnysayzz

    root cause is in get_head_branch (git.py:877). on a shallow tag checkout there is no refs/remotes/origin/HEAD, so head_splitter returns None and branch.startswith('-') blows up. that check came in with the CVE-2026-84503 cleanup in 5186cff, which never handled the None case.

    fix guards the None and returns it like 2.21.4 did, dash names still get rejected. added a regression test covering the exact layout from the repro plus a changelog fragment. fix is in #87883.

  5. added 5 commits that reference this issue on Nov 5, 2026
    a3e697b
    6b85698
    0001987
    a464515
    4585aba
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    affects_2.21This issue/PR affects Ansible v2.21bugThis issue/PR relates to a bug.has_prThis issue has an associated PR.moduleThis issue/PR relates to a module.needs_triageNeeds a first human triage before being processed.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0