Introduction

Starting with ansible-core 2.20 (Ansible 14), the skipped_reason result key is deprecated in favor of skip_reason. If you see the warning The 'skipped_reason' value is deprecated, your callback plugins or custom code needs updating before this becomes an error in a future release.

The Warning

[DEPRECATION WARNING]: The 'skipped_reason' value is deprecated, 
use 'skip_reason' instead. This feature will be removed in a future release.

This appears when:

  • A callback plugin accesses result._result['skipped_reason']
  • Custom action plugins set skipped_reason in results
  • Third-party collections use the old key name

The Fix

Callback Plugins

# ❌ Old (deprecated)
class CallbackModule(CallbackBase):
    def v2_runner_on_skipped(self, result):
        reason = result._result.get('skipped_reason', '')
        self._display.display(f"SKIPPED: {reason}")

# ✅ New (correct)
class CallbackModule(CallbackBase):
    def v2_runner_on_skipped(self, result):
        reason = result._result.get('skip_reason', '')
        self._display.display(f"SKIPPED: {reason}")

Backward-Compatible Fix

# ✅ Works with both old and new Ansible versions
class CallbackModule(CallbackBase):
    def v2_runner_on_skipped(self, result):
        reason = result._result.get('skip_reason',
                 result._result.get('skipped_reason', ''))
        self._display.display(f"SKIPPED: {reason}")

Action Plugins

# ❌ Old
return dict(
    skipped=True,
    skipped_reason="Host not in target group"
)

# ✅ New
return dict(
    skipped=True,
    skip_reason="Host not in target group"
)

Playbook Impact

Standard playbooks using when conditions are not affected — this is an internal API change for plugin developers. However, if you register results and check skipped_reason:

# ❌ May break in future
- name: Run conditional task
  ansible.builtin.command: echo hello
  when: inventory_hostname in group_names
  register: result

- name: Show skip reason (old way)
  ansible.builtin.debug:
    msg: "{{ result.skipped_reason | default('') }}"
  when: result.skipped | default(false)

# ✅ Future-proof
- name: Show skip reason (new way)
  ansible.builtin.debug:
    msg: "{{ result.skip_reason | default(result.skipped_reason | default('')) }}"
  when: result.skipped | default(false)

Check Your Code

# Find uses of skipped_reason in your project
grep -r "skipped_reason" roles/ plugins/ callback_plugins/ 2>/dev/null

# Find in installed collections
grep -r "skipped_reason" ~/.ansible/collections/ 2>/dev/null

# Find in custom callback plugins
grep -r "skipped_reason" /usr/share/ansible/plugins/callback/ 2>/dev/null

Common Affected Components

ComponentAction
Custom callback pluginsReplace skipped_reason → skip_reason
Custom action pluginsUpdate return dict key
Third-party collectionsUpdate collection or wait for fix
Playbooks using registerAdd fallback: skip_reason | default(skipped_reason)
ansible.cfg callback settingsNo change needed

Timeline

VersionBehavior
ansible-core ≤2.19skipped_reason works, no warning
ansible-core 2.20 (Ansible 14 RC)Warning displayed
ansible-core 2.21+ (future)skipped_reason removed — error

Troubleshooting

IssueSolution
Warning appears but no custom pluginsA collection's callback plugin uses it — update the collection
Warning in CI/CD outputAdd grep -v "DEPRECATION WARNING" or fix the source
Can't find the sourceRun with -vvv to see which plugin triggers it
Need to support both old and newUse fallback pattern: get('skip_reason', get('skipped_reason'))

Best Practices

  1. Fix now, not later — deprecations become errors in the next major
  2. Use the fallback pattern for backward compatibility
  3. Update collections — ansible-galaxy collection install --upgrade
  4. Test with Ansible 14 RC — pip install ansible==14.0.0rc1
  5. Search your codebase — grep -r skipped_reason catches everything

Conclusion

Replace skipped_reason with skip_reason in all callback plugins, action plugins, and playbook result checks. Use the fallback pattern (skip_reason | default(skipped_reason)) if you need to support multiple Ansible versions. Fix it now — this becomes a hard error in a future ansible-core release.