How to Retry a Failed Task in Ansible (retries, delay, until)
By Luca Berton · Published 2024-01-01 · Category: installation
How to retry failed tasks in Ansible using retries, delay, and until. Handle transient failures, wait for services, and implement resilient playbooks.
How to Retry a Failed Task in Ansible (retries, delay, until)
Transient failures happen — APIs timeout, services take time to start, packages fail to download. Ansible's retry mechanism handles this gracefully.
See also: Ansible retries & until: Retry Failed Tasks Automatically (Guide)
Basic Retry
- name: Wait for web server to respond
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
register: result
until: result.status == 200
retries: 30
delay: 5
# Tries every 5 seconds, up to 30 times (2.5 minutes)
Retry Package Installation
- name: Install packages (retry on network issues)
ansible.builtin.apt:
name:
- nginx
- postgresql-client
state: present
update_cache: true
register: apt_result
until: apt_result is success
retries: 3
delay: 10
See also: How to Check if a File Exists in Ansible (4 Methods)
Retry with Complex Conditions
- name: Wait for database to accept connections
ansible.builtin.command: pg_isready -h {{ db_host }}
register: pg_ready
until: pg_ready.rc == 0
retries: 60
delay: 2
changed_when: false
- name: Wait for specific log entry
ansible.builtin.command: grep "Server started" /var/log/myapp/app.log
register: log_check
until: log_check.rc == 0
retries: 30
delay: 5
changed_when: false
failed_when: false
Retry API Calls
- name: Create DNS record (retry on rate limit)
ansible.builtin.uri:
url: https://api.cloudflare.com/v4/zones/{{ zone_id }}/dns_records
method: POST
headers:
Authorization: "Bearer {{ vault_cf_token }}"
body_format: json
body:
type: A
name: "{{ hostname }}"
content: "{{ ip_address }}"
status_code: [200, 409] # 409 = already exists (ok)
register: dns_result
until: dns_result.status in [200, 409]
retries: 5
delay: 30 # Respect rate limits
See also: How to Do Rolling Updates with Zero Downtime in Ansible
Retry with Backoff Pattern
# Ansible doesn't have native exponential backoff,
# but you can approximate with a loop:
- name: Retry with increasing delay
ansible.builtin.uri:
url: https://api.example.com/status
status_code: 200
register: api_check
until: api_check.status == 200
retries: 5
delay: "{{ item }}"
loop: [5, 10, 20, 40, 60]
when: api_check is not defined or api_check.status != 200
Default Values
Without explicit parameters: • retries defaults to 3 • delay defaults to 5 seconds • until is required for retries to activate
FAQ
How do I retry a failed task in Ansible?
Use until, retries, and delay on any task: until: result is success with retries: 5 and delay: 10. The task retries up to 5 times, waiting 10 seconds between attempts.
What is the difference between retries and block/rescue?
retries re-attempts the same task multiple times (good for transient failures). block/rescue catches failures and runs alternative recovery tasks (good for fallback logic).
Does Ansible support exponential backoff?
Not natively. The delay is fixed between retries. For exponential backoff, use a loop with increasing delay values or implement it in a custom module.
Related Articles
• Ansible Error Handling: block/rescue/always • Ansible uri Module: HTTP Requests • Ansible Playbook GuideCommon Retry Patterns
- name: Retry patterns
hosts: all
tasks:
# Wait for a service to become available
- name: Wait for API to respond
ansible.builtin.uri:
url: http://localhost:8080/health
status_code: 200
register: result
until: result.status == 200
retries: 30
delay: 10
# Wait for apt lock to release
- name: Install package (retry on lock)
ansible.builtin.apt:
name: nginx
state: present
register: apt_result
until: apt_result is succeeded
retries: 5
delay: 30
# Wait for cloud instance to be reachable
- name: Wait for SSH
ansible.builtin.wait_for:
host: "{{ ansible_host }}"
port: 22
timeout: 300
delegate_to: localhost
Retry vs Block/Rescue
# Use block/rescue for different recovery actions
- name: Try primary, fall back to secondary
block:
- name: Try primary mirror
ansible.builtin.get_url:
url: https://primary.example.com/package.tar.gz
dest: /tmp/package.tar.gz
rescue:
- name: Fall back to secondary mirror
ansible.builtin.get_url:
url: https://secondary.example.com/package.tar.gz
dest: /tmp/package.tar.gz
FAQ
What is the default number of retries?
The default is 3 retries with 5 seconds delay. Always set explicit values for clarity.
Can I use retries with any module?
Yes. retries, delay, and until work with any module. The until condition evaluates the registered result.
What happens when all retries are exhausted?
The task fails with the last error. Use ignore_errors: true or block/rescue to handle the failure gracefully.
Category: installation