Aller au contenu
Infrastructure as Code medium

ignore_errors Ansible : usage légitime vs anti-pattern

10 min de lecture

Logo Ansible

ignore_errors: true indique à Ansible de ne pas considérer une tâche en échec comme bloquante, le play continue malgré l'erreur. C'est une directive simple à utiliser mais souvent un anti-pattern : elle masque les vraies erreurs, rend le diagnostic difficile, et peut laisser un système dans un état incohérent. Cette page liste les rares cas légitimes d'usage, et explique pourquoi failed_when: ou block/rescue/always sont presque toujours préférés.

ansible-lint profil production signale les ignore_errors: true comme problème (ignore-errors), sauf certaines exceptions documentées.

  • L'effet de ignore_errors: true (la tâche échouée est marquée ignored, le play continue)
  • Les 3 cas légitimes où c'est justifié
  • Pourquoi failed_when: est souvent une meilleure réponse
  • Pourquoi block/rescue/always est presque toujours plus propre
  • L'impact dans le PLAY RECAP : ignored=N
- name: Tâche qui échoue
ansible.builtin.command: /bin/false
ignore_errors: true
- name: Tâche suivante (s'exécute quand même)
ansible.builtin.debug:
msg: "Le play continue"

PLAY RECAP : ok=1 changed=1 failed=0 ignored=1. La tâche en échec est marquée ignored=1 (visible dans le RECAP), le play continue.

Une opération de cleanup où l'échec n'est pas critique :

- name: Tenter de stopper un service (peut ne pas exister)
ansible.builtin.systemd:
name: legacy-service
state: stopped
ignore_errors: true

Si le service n'existe pas, on s'en fiche, c'est exactement ce qu'on voulait. Mais mieux :

# ✅ Plus propre avec failed_when:
- name: Tenter de stopper un service legacy
ansible.builtin.systemd:
name: legacy-service
state: stopped
failed_when: false

failed_when: false est explicite : "ne jamais marquer cette tâche comme failed".

Vérifier la présence d'un binaire pour conditionner les tâches suivantes :

- name: Vérifier la présence de docker
ansible.builtin.command: which docker
register: docker_check
ignore_errors: true
changed_when: false
- name: Configurer Docker (si présent)
ansible.builtin.copy:
src: daemon.json
dest: /etc/docker/daemon.json
when: docker_check.rc == 0

Mieux : failed_when: false ou block/rescue :

# ✅ failed_when: false plus explicite
- name: Vérifier la présence de docker
ansible.builtin.command: which docker
register: docker_check
changed_when: false
failed_when: false

Cas 3, Opération attendue d'échouer dans un block/rescue

Section intitulée « Cas 3, Opération attendue d'échouer dans un block/rescue »

Très rarement utile, car block/rescue capture déjà les erreurs proprement :

- block:
- name: Tenter une opération
ansible.builtin.command: /usr/local/bin/risky.sh
ignore_errors: true # ← inutile dans un block
rescue:
- name: Cleanup
ansible.builtin.debug:
msg: "Erreur capturée"

ignore_errors: à l'intérieur d'un block empêche le rescue de se déclencher (puisque la tâche n'est plus marquée failed). À éviter.

Trois raisons :

  1. Masque les vraies erreurs : un échec inattendu ne lève plus la main. Le bug se manifeste plus tard, ailleurs, sans contexte.

  2. Pollue le diagnostic : un ignored=12 dans le PLAY RECAP est inutilement alarmant, vous devez chercher dans les logs lesquelles ont vraiment échoué.

  3. Empêche block/rescue : si vous mettez ignore_errors: true dans un block, le rescue n'est jamais déclenché. Vous perdez le bénéfice de la gestion structurée.

Cas pratique, ignore_errors dans un play simple (lab ecrire-code/ignore-errors)

Section intitulée « Cas pratique, ignore_errors dans un play simple (lab ecrire-code/ignore-errors) »

Voici l'exemple validé sur le lab 24-ecrire-code-ignore-errors :

- name: Challenge ignore errors
hosts: db1.lab
become: true
tasks:
- name: Stopper un service inexistant
ansible.builtin.systemd:
name: ce-service-nexiste-pas
state: stopped
ignore_errors: true
- name: Marqueur post ignore
ansible.builtin.copy:
dest: /tmp/ignore-after.txt
content: "play continued\n"
mode: "0644"

PLAY RECAP : ok=1 changed=1 failed=0 ignored=1. La tâche suivante s'est bien exécutée.

Réécriture préférée sans ignore_errors: :

- name: Stopper un service legacy si présent
ansible.builtin.systemd:
name: ce-service-nexiste-pas
state: stopped
failed_when: false # ← explicite, pas de "ignored" dans RECAP
MécanismeAvantageInconvénient
ignore_errors: trueSimple à écrireMasque les erreurs ; pollue PLAY RECAP
failed_when: falseExplicite : "jamais d'échec"À utiliser avec parcimonie aussi
failed_when: <expr>Précis : on définit ce qui constitue un échecPlus verbeux
block / rescue / alwaysCapture + réagit (notification, cleanup)Plus de structure

Règle pratique : si vous écrivez ignore_errors: true, demandez-vous d'abord si l'une des 3 alternatives ne ferait pas mieux. Dans 99 % des cas, oui.

SymptômeCauseFix
ignored=N dans PLAY RECAP, on ne sait pas quoi a échouéC'est par designPréférer failed_when: ou block/rescue qui montrent le détail
ignore_errors: true dans un block, le rescue ne se déclenche pasC'est attenduRetirer ignore_errors: ; laisser le rescue capturer
ansible-lint signale ignore-errorsAnti-pattern détectéMigrer vers failed_when: ou block/rescue
ignore_errors: true cumulé avec failed_when:Comportement ambiguChoisir l'un ou l'autre, pas les deux
  • ignore_errors: true marque la tâche ignored=1 mais ne fait pas planter le play.
  • 3 cas légitimes, mais dans 99 % des cas, failed_when: ou block/rescue sont préférés.
  • failed_when: false est plus explicite que ignore_errors: true pour "ne jamais échouer".
  • ignore_errors: true dans un block empêche le rescue, anti-pattern.
  • ansible-lint profil production signale ignore-errors comme un problème.

Cette page a un lab d'accompagnement : labs/ecrire-code/ignore-errors/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : continuer un play malgré l'échec d'une tâche grâce à ignore_errors: true.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/ignore-errors/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si les tests passent, vous maîtrisez les concepts couverts dans ce guide. En cas de blocage, docs/troubleshooting.md à la racine du repo couvre les pièges fréquents (rate-limit SSH, clé absente, collection manquante).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn