I’m not even gonna waste my time with the rant. Example code:
# rc = 1 both when expires, and when doesn't exist / not a valid cert
- name: Check current cert expiry
command:
cmd: "openssl x509 -checkend {{ eff_min_days | int * 86400 }} -noout -in {{ deploy_cert_file }}"
changed_when: false
failed_when: current_expiry.rc != 0 and current_expiry.stderr | length
register: current_expiry
After 2.19, this produces the following error:
TASK [repo : Check current cert expiry] ****************************************
[ERROR]: Task failed: Module failed: non-zero return code
Origin: /repo/tasks/acme.yml:16:3
14
15 # rc = 1 both when expires, and when doesn't exist / not a valid cert
16 - name: Check current cert expiry
^ column 3
fatal: [127.0.0.1]: FAILED! => {"changed": false, "cmd": ["openssl", "x509", "-checkend", "7776000", "-noout", "-in", "/etc/acme/ubuntu-24-172044a.vault-tec.info/ubuntu-24-172044a.vault-tec.info.cer"], "delta": "0:00:00.028063", "end": "2026-03-02 17:22:21.888682", "failed_when_result": "Conditional result (False) was derived from value of type 'int' at '/repo/tasks/acme.yml:20:16'. Conditionals must have a boolean result.", "msg": "non-zero return code", "rc": 1, "start": "2026-03-02 17:22:21.860619", "stderr": "", "stderr_lines": [], "stdout": "Certificate will expire", "stdout_lines": ["Certificate will expire"]}
PLAY RECAP *********************************************************************
127.0.0.1 : ok=44 changed=7 unreachable=0 failed=1 skipped=12 rescued=0 ignored=0
It has something to do with implicit boolean conversions, but what exactly, I’m yet to figure out. I have plenty of places with such code in use, and this is the first to break with it. I don’t really care either TBH. The solution is explicitly checking for length to be greater than 0.
failed_when: current_expiry.rc != 0 and current_expiry.stderr | length > 0
Now that’s so much better, right? This code is now safe and readable and all that jazz, the world is saved, etc. I hope all the Ansible devs are happy now.
