Skip to content

Respect retries when a deferrable trigger ends a task with TaskFailedEvent#69821

Open
hkc-8010 wants to merge 1 commit into
apache:mainfrom
hkc-8010:fix/deferred-task-failed-event-respects-retries
Open

Respect retries when a deferrable trigger ends a task with TaskFailedEvent#69821
hkc-8010 wants to merge 1 commit into
apache:mainfrom
hkc-8010:fix/deferred-task-failed-event-respects-retries

Conversation

@hkc-8010

@hkc-8010 hkc-8010 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

When a deferrable operator's trigger yields a terminal TaskFailedEvent, the task was always marked failed and its on_failure_callback ran, even when the task still had retries remaining. A worker-side failure with retries left instead goes up_for_retry and runs on_retry_callback. This makes trigger-driven failures behave the same way.

The BaseTaskEndEvent handler in airflow-core/src/airflow/models/trigger.py now, for a FAILED event, loads the serialized task and routes through TaskInstance.handle_failure(), the same path the scheduler executor-event handling has used since #56586. handle_failure sets up_for_retry or failed based on retry-eligibility and fires the on_task_instance_failed listener, failure metrics, and a Log entry. The callback request now carries the resolved task_callback_type so the DAG processor runs on_retry_callback vs on_failure_callback correctly. TaskSuccessEvent and TaskSkippedEvent are unchanged.

closes: #69819

Changes

  • airflow-core/src/airflow/models/trigger.py: route trigger-emitted failures through handle_failure, thread the retry-aware task_callback_type into the callback, and skip the xcom push on the retry path.
  • airflow-core/tests/unit/models/test_trigger.py: new parametrized test covering the retry-eligible case (up_for_retry + on_retry_callback + on_task_instance_failed listener) and the exhausted case (failed + on_failure_callback); the existing end-event test now sets a realistic start_date (a deferred task has already run).
  • airflow-core/newsfragments/69821.bugfix.rst.

Testing

  • pytest airflow-core/tests/unit/models/test_trigger.py (39 passed).
  • Confirmed the new test fails on main (the task stays failed and the callback is routed as a failure) and passes with this change.

This change was written with AI assistance (Claude); the author reviewed the diff and reproduction.

…Event

When a deferrable operator's trigger yields a terminal TaskFailedEvent, the task
was always marked failed and on_failure_callback ran, even with retries remaining.
A worker-side failure with retries left instead goes up_for_retry and runs
on_retry_callback. Route trigger-emitted failures through TaskInstance.handle_failure
(the path the scheduler has used since apache#56586) so retry-eligibility is respected and
the callback runs on_retry_callback vs on_failure_callback accordingly.

closes: apache#69819

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hkc-8010 hkc-8010 force-pushed the fix/deferred-task-failed-event-respects-retries branch from 4017af8 to 5dfb1ce Compare July 13, 2026 11:17
@hkc-8010 hkc-8010 marked this pull request as ready for review July 13, 2026 12:17
@hkc-8010 hkc-8010 requested review from XD-DENG and ashb as code owners July 13, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deferrable task that ends via TaskFailedEvent ignores retries and always runs on_failure_callback

1 participant