diff --git a/changelogs/fragments/70240-fix-fatal-post_validate-error.yml b/changelogs/fragments/70240-fix-fatal-post_validate-error.yml new file mode 100644 index 00000000000..ca2fc8a1e2a --- /dev/null +++ b/changelogs/fragments/70240-fix-fatal-post_validate-error.yml @@ -0,0 +1,2 @@ +bugfixes: + - TaskExecutor - Handle unexpected errors as failed while post validating loops (https://github.com/ansible/ansible/issues/70050). diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 0cffacc7355..53998eec060 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -584,7 +584,12 @@ class TaskExecutor: return dict(include_args=include_args) # Now we do final validation on the task, which sets all fields to their final values. - self._task.post_validate(templar=templar) + try: + self._task.post_validate(templar=templar) + except AnsibleError: + raise + except Exception: + return dict(changed=False, failed=True, _ansible_no_log=self._play_context.no_log, exception=to_text(traceback.format_exc())) if '_variable_params' in self._task.args: variable_params = self._task.args.pop('_variable_params') if isinstance(variable_params, dict): diff --git a/test/integration/targets/lookups/tasks/errors.yml b/test/integration/targets/lookups/tasks/errors.yml new file mode 100644 index 00000000000..da57631a8d1 --- /dev/null +++ b/test/integration/targets/lookups/tasks/errors.yml @@ -0,0 +1,31 @@ +- name: Task that fails due to templating error for plugin option + debug: msg="{{ 5 / 0 | int }}" + ignore_errors: true + register: result + +- assert: + that: + - result.failed + - result.exception + +- name: Loop that fails due to templating error in first entry and ignores errors + debug: msg="{{ 5 / item }}" + ignore_errors: true + register: result + loop: [0, 0, 1] + +- debug: var=result + +- assert: + that: + - result.results[0].failed + - result.results[0].exception + - result.results[0].item == 0 + + - result.results[1].failed + - result.results[1].exception + - result.results[1].item == 0 + + - not result.results[2].failed + - result.results[2].exception is undefined + - result.results[2].item == 1 diff --git a/test/integration/targets/lookups/tasks/main.yml b/test/integration/targets/lookups/tasks/main.yml index 452515261b4..5e723719ea5 100644 --- a/test/integration/targets/lookups/tasks/main.yml +++ b/test/integration/targets/lookups/tasks/main.yml @@ -288,6 +288,8 @@ that: - "hello_world_string|trim == 'Hello world!'" +- include_tasks: ./errors.yml + # Vars lookups - name: Test that we can give it a single value and receive a single value