The Problem

You added notify: restart nginx but the handler never runs.

Cause 1: Name Mismatch

# WRONG — names don't match exactly
tasks:
  - name: Update config
    ansible.builtin.copy:
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
    notify: Restart nginx  # Capital R

handlers:
  - name: restart nginx   # lowercase r ← MISMATCH
    ansible.builtin.service:
      name: nginx
      state: restarted

Handler names are case-sensitive. They must match exactly.

Cause 2: Task Didn't Change Anything

Handlers only run when the task reports changed. If the file is already identical:

TASK [Update config] ****
ok: [server]  ← "ok" not "changed" — handler won't fire

Force a change to test:

- name: Touch config to force change
  ansible.builtin.file:
    path: /etc/nginx/nginx.conf
    state: touch
  notify: restart nginx
  changed_when: true  # Force "changed" status

Cause 3: Task Failed Before Handler Ran

Handlers run at the end of the play, not immediately after notify. If a later task fails, handlers are skipped.

# Fix: force handlers to run mid-play
tasks:
  - name: Update config
    ansible.builtin.copy:
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
    notify: restart nginx

  - name: Force handlers now
    ansible.builtin.meta: flush_handlers

  - name: This might fail
    ansible.builtin.command: /opt/risky-script.sh

Or use --force-handlers:

ansible-playbook playbook.yml --force-handlers

Cause 4: Handler in Wrong Section

# WRONG — handler defined as a task
tasks:
  - name: restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

# RIGHT — handler in handlers section
handlers:
  - name: restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

Cause 5: Listen vs Name

# Using listen for multiple notifications
tasks:
  - name: Update app config
    ansible.builtin.template:
      src: app.conf.j2
      dest: /etc/app/app.conf
    notify: restart app stack

handlers:
  - name: restart app
    ansible.builtin.service:
      name: myapp
      state: restarted
    listen: restart app stack

  - name: restart worker
    ansible.builtin.service:
      name: myapp-worker
      state: restarted
    listen: restart app stack

Debugging Handlers

# Verbose output shows handler notifications
ansible-playbook playbook.yml -vv

# Look for:
# NOTIFIED HANDLER restart nginx
# RUNNING HANDLER [restart nginx]

Conclusion

Handlers not running? Check: exact name match, task actually changed something, no failures before handler execution. Use meta: flush_handlers when you need handlers to run immediately.