Introduction

The failure downloading error is one of the most common issues when working with Ansible modules that fetch content from the internet — including get_url, unarchive, yum, apt, and uri. This error occurs when Ansible cannot successfully download a resource from a specified URL.

In this guide, you'll learn the root causes of download failures and how to fix each one systematically.

Understanding the Error

The failure downloading error appears when Ansible attempts to fetch a resource from a URL and the download fails. The error output typically includes:

fatal: [host]: FAILED! => {"changed": false, "msg": "Failure downloading https://example.com/file.zip, Request failed: <urlopen error ...>"}

Or with the yum module:

fatal: [host]: FAILED! => {"changed": false, "msg": "Failure downloading https://repo.example.com/package.rpm: HTTP Error 404 - Not Found"}

Common Causes and Solutions

1. Incorrect URL (HTTP 404)

The most frequent cause — a misspelled URL or content that has been moved.

Diagnosis: Try the URL in a browser or with curl:

curl -I https://github.com/user/repo/archive/refs/master.zip
# HTTP/1.1 404 Not Found

Fix: Verify the correct URL format:

# WRONG - missing /heads/ in GitHub archive URL
- name: Download archive (broken)
  ansible.builtin.unarchive:
    src: "https://github.com/myuser/myrepo/archive/refs/master.zip"
    dest: /opt/app/
    remote_src: true

# CORRECT - include /heads/ for branch archives
- name: Download archive (fixed)
  ansible.builtin.unarchive:
    src: "https://github.com/myuser/myrepo/archive/refs/heads/master.zip"
    dest: /opt/app/
    remote_src: true

2. SSL/TLS Certificate Issues

Self-signed certificates or outdated CA bundles cause SSL verification failures.

Error message:

Failure downloading: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed>

Fix (temporary — for testing only):

- name: Download with certificate skip (NOT for production)
  ansible.builtin.get_url:
    url: https://internal-server.local/package.tar.gz
    dest: /tmp/package.tar.gz
    validate_certs: false

Fix (proper — add custom CA):

- name: Download with custom CA bundle
  ansible.builtin.get_url:
    url: https://internal-server.local/package.tar.gz
    dest: /tmp/package.tar.gz
    ca_path: /etc/pki/tls/certs/internal-ca.pem

3. Network Connectivity Issues

The remote host cannot reach the download URL due to firewall rules, proxy requirements, or DNS issues.

Diagnosis:

- name: Test connectivity
  ansible.builtin.uri:
    url: https://example.com
    method: HEAD
    status_code: [200, 301, 302]
  register: connectivity_test
  ignore_errors: true

- name: Show result
  ansible.builtin.debug:
    msg: "Connection {{ 'successful' if connectivity_test is success else 'failed: ' + connectivity_test.msg }}"

Fix — configure proxy:

- name: Download through proxy
  ansible.builtin.get_url:
    url: https://example.com/file.tar.gz
    dest: /tmp/file.tar.gz
  environment:
    http_proxy: http://proxy.example.com:3128
    https_proxy: http://proxy.example.com:3128
    no_proxy: "localhost,127.0.0.1,.internal.local"

4. Authentication Required

The resource requires credentials for access.

Error message:

Failure downloading: HTTP Error 401 - Unauthorized

Fix:

- name: Download from authenticated source
  ansible.builtin.get_url:
    url: https://artifacts.example.com/releases/app-2.0.tar.gz
    dest: /tmp/app-2.0.tar.gz
    url_username: "{{ vault_artifact_user }}"
    url_password: "{{ vault_artifact_password }}"
    force_basic_auth: true

5. Timeout on Slow Connections

Large files or slow connections may exceed the default timeout.

Fix:

- name: Download large file with extended timeout
  ansible.builtin.get_url:
    url: https://releases.example.com/large-app-500mb.tar.gz
    dest: /opt/downloads/large-app.tar.gz
    timeout: 300  # 5 minutes

6. Repository Package Download Failure (yum/apt)

Package manager modules may fail when repository URLs are stale or mirrors are down.

Error:

Failure downloading https://mirror.centos.org/centos/7/os/x86_64/Packages/package-1.0.rpm

Fix:

- name: Clean yum cache and retry
  block:
    - name: Install package
      ansible.builtin.yum:
        name: httpd
        state: present
  rescue:
    - name: Clean yum cache
      ansible.builtin.command: yum clean all
      changed_when: true

    - name: Retry package install
      ansible.builtin.yum:
        name: httpd
        state: present

Complete Troubleshooting Playbook

---
- name: Robust file download with error handling
  hosts: all
  vars:
    download_url: "https://github.com/myuser/myrepo/archive/refs/heads/main.zip"
    download_dest: "/tmp/myrepo.zip"
    download_checksum: "sha256:abc123def456..."
  tasks:
    - name: Verify URL is reachable
      ansible.builtin.uri:
        url: "{{ download_url }}"
        method: HEAD
        status_code: [200, 302]
        timeout: 10
      register: url_check
      ignore_errors: true

    - name: Fail with helpful message if URL unreachable
      ansible.builtin.fail:
        msg: |
          Cannot reach {{ download_url }}
          Status: {{ url_check.status | default('connection failed') }}
          Error: {{ url_check.msg | default('unknown') }}
          Troubleshooting:
            1. Check URL is correct and resource exists
            2. Verify network/proxy settings on {{ inventory_hostname }}
            3. Check DNS resolution: nslookup {{ download_url | urlsplit('hostname') }}
            4. Test with curl: curl -I {{ download_url }}
      when: url_check is failed

    - name: Download file with checksum verification
      ansible.builtin.get_url:
        url: "{{ download_url }}"
        dest: "{{ download_dest }}"
        checksum: "{{ download_checksum }}"
        timeout: 120
        mode: '0644'
      register: download_result
      retries: 3
      delay: 10
      until: download_result is success

    - name: Extract archive
      ansible.builtin.unarchive:
        src: "{{ download_dest }}"
        dest: /opt/app/
        remote_src: true
      when: download_result is success

Prevention Checklist

  1. Always test URLs manually before using them in playbooks
  2. Use checksums (checksum parameter) to verify file integrity
  3. Add retries for transient network issues
  4. Set appropriate timeouts based on file size and network speed
  5. Use block/rescue for graceful failure handling
  6. Pin versions in URLs rather than using "latest" paths that may change
  7. Mirror files locally for air-gapped or unreliable network environments

Conclusion

The failure downloading error in Ansible is almost always caused by an incorrect URL, network issue, or certificate problem. By systematically verifying connectivity, checking URLs, and implementing retry logic, you can build resilient playbooks that handle download failures gracefully. Always test URLs manually first and use checksums to ensure file integrity.