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 tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn