Notification, flush and another execution
The experiment forces changed on two debug tasks to produce controlled notifications. The handler runs once at the explicit flush. A third later notification permits another execution at play end. Events show two handler executions, first changed=true and then changed=false, because lineinfile preserves a single activated line. This distinguishes execution from additional effect. No real service was reloaded. In a production playbook, review when notifications arise and where they are consumed instead of counting changed messages as independent activations of the service.
A failure may leave a candidate on disk
The second experiment copies a candidate, notifies a handler and deliberately fails a following task. Without force_handlers, the candidate exists and no activation marker is created. The process exits with code two. This represents partial state: a write occurred before failure. Recap helps locate tasks, but recovery decisions need per-target state. In middleware, a new file and a process still using the previous generation may coexist. Record that difference before rerunning, cleaning up or declaring the change complete to the receiving team.
Force_handlers does not validate the candidate
With force_handlers=true, the same experiment creates the activation marker despite failure after notification; the process still exits with code two. The setting changes handling of notified handlers, not candidate correctness or overall success. Documentation also notes that conditions such as an unreachable host may prevent execution. For real configuration, place validation, publication and notification in the appropriate order. A gate placed after notification may be insufficient if activation remains eligible following that failure. Review this sequence together with the module’s actual validation behavior.
Rescue handles flow, not effects
The original block writes candidate.cfg and deliberately fails. Rescue only saves the failed task name, while always writes observations. Execution exits zero, recap records a rescued failure and the candidate remains. The example demonstrates flow handling without restoration tasks. Do not assign rollback meaning to the name rescue. If recovery requires restoring configuration, data or traffic, those actions and their validation need to exist. Preserve the original failure and distinguish it from errors that may arise during recovery itself or during later acceptance checks.
Define what accepting the change means
Acceptance needs to connect intent to an observable outcome: validated candidate, target publication, active generation and consumer journey. A zero code, present file or executed handler is insufficient. Also define the result when an observation is missing instead of converting it into success. In the lab, hashes identify artifacts used and the executor is pinned to ansible-core 2.21.4. This traceability supports repeating the bounded experiment; it is neither vendor certification nor independent validation of a production environment or its operational controls.
Partial-state handover workshop
In the final case, two hosts activated B, one received only the B file and two remain on A. The consumer has not been validated and the window is ending. Hand over a per-host table containing disk generation, active generation, failed task, evidence and outstanding action. Assign owners and the next authorized decision, including recovery or another window when needed. Communicate: “The rollout is partial; consumer acceptance remains outstanding.” Handler counts do not replace this handover. The aim is continuity without forcing the next shift to reconstruct state from an ambiguous summary.
Two notifications before flush: one execution. A new later notification: a second execution. Successful rescue: zero exit with candidate.cfg still changed. These are local observations without a real reload.
Common pitfalls
Counting changed as activations; assuming unconditional execution of forced handlers; calling any rescue a rollback; closing on zero exit without observing state; omitting the original failure.
Related topics: Tasks and desired state · Batch orchestration · Failures and recovery
Control validation and activation order. Reconstruct effects per target and claim recovery or acceptance only when evidence matches the intended outcome.
Reference: Blocks · Ansible community 14 / ansible-core 2.21 documentation consulted 2026-09-30; executor, collection and plugin compatibility requires confirmation