Skip to content

Stop ExternalTaskSensor waiting for missing Dags on Airflow 3.2+ - #72517

Closed
ignacioparicio wants to merge 2 commits into
apache:mainfrom
ignacioparicio:fix-external-task-sensor-check-existence-af3
Closed

ignacioparicio wants to merge 2 commits into
apache:mainfrom
ignacioparicio:fix-external-task-sensor-check-existence-af3

Conversation

@ignacioparicio

@ignacioparicio ignacioparicio commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

ExternalTaskSensor(check_existence=True) is supposed to fail immediately when the external Dag does not exist. On Airflow 3 it does not check at all. When external_dag_id refers to a Dag that does not exist, the sensor waits until its timeout instead of reporting the problem immediately.

The same thing happens when waiting is handed off to the triggerer (deferrable=True): the wait starts without a check.

Note:

  • Airflow 2 is not affected.
  • This only changes behavior for sensors with check_existence=True.
Where it happens

In providers/standard/src/airflow/providers/standard/sensors/external_task.py:

def _poke_af3(self, context: Context, dttm_filter: Sequence[datetime.datetime]) -> bool:
    from airflow.providers.standard.utils.sensor_helper import _get_count_by_matched_states

    self._has_checked_existence = True  # set here, then never read again
    ti = context["ti"]

_has_checked_existence is meant to stop the same check from being repeated. In the Airflow 3 code it is set before any check has happened.

The check itself is behind this condition:

if self.check_existence and not self._has_checked_existence:
    self._check_for_existence(session=session)

Both copies of the condition are in Airflow 2-only code, so Airflow 3 never calls _check_for_existence.

How it got here

The existing check reads the metadata database and the Dag file. An Airflow 3 worker has access to neither, so it cannot use that implementation.

The missing piece was a way for a worker to ask whether a Dag exists. #56955 added that to the execution API in Airflow 3.2.

#67832 explored a broader check for individual tasks and task groups. It was closed because the answer depends on the Dag version used by a particular run. This PR does not add a new API. It uses the existing Dag lookup only to answer whether the external Dag itself exists.

What this PR does:

  • external_task.py: on Airflow 3.2 and later, asks the execution API whether the external Dag exists before the sensor starts waiting. A missing Dag raises ExternalDagNotFoundError; other API errors are left unchanged.
  • external_task.py: applies the check whether the sensor waits itself or hands the wait to the triggerer, and documents the limits below.
  • test_external_task_sensor.py: covers both ways of waiting, repeated checks, unexpected API errors, and older Airflow 3 versions.

What this PR does not fix:

  • On Airflow 3, external_task_ids and external_task_group_id are still not checked. The external Dag is checked, but the execution API cannot say whether a task exists in the Dag version used by a particular run. When an external task or task group is configured, the sensor now warns that only the external Dag was checked. The full task and task-group check is not part of this PR.
  • Airflow 3.0 and 3.1 cannot perform the Dag check because the required execution API was added in Airflow 3.2. They also log a warning and keep the existing behavior.

related: #72514


Was generative AI tooling used to co-author this PR?
  • Yes, Codex (GPT-5)

Used to trace the regression through the history above, check what an Airflow 3 worker can ask the execution API, and review the implementation and tests.

@jroachgolf84

Copy link
Copy Markdown
Collaborator

closes: #72514

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.

@github-actions github-actions Bot added the stale Stale PRs per the .github/workflows/stale.yml policy file label Oct 20, 2026
@github-actions github-actions Bot closed this Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providers provider:standard stale Stale PRs per the .github/workflows/stale.yml policy file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants