luc-pimentel opened a new issue, #75134:
URL: https://github.com/apache/airflow/issues/75134

   ### Under which category would you file this issue?
   
   Airflow Core
   
   ### Apache Airflow version
   
   3.3.2; also reproduced on main on October 19, 2026.
   
   ### What happened and how to reproduce it?
   
   `PATCH /api/v2/dags/{dag_id}/dagRuns/{run_id}/taskInstances/{task_id}` with 
`{"new_state": "success", "include_future": true}` on a manually triggered run 
(no logical date) marks the task in that run only, but then clears the 
`failed`/`upstream_failed` downstream tasks of the Dag's other runs and sets 
those runs back to `queued`. The response lists only the target run, so the 
caller does not see it. `include_past` behaves the same, and so does the bulk 
`PATCH .../taskInstances` body. The clear route refuses this combination with 
400 (#47036), and the Mark-as dialog disables Past and Future for such runs.
   
   Dag file:
   
   ```python
   import pendulum
   from airflow.providers.standard.operators.bash import BashOperator
   from airflow.providers.standard.operators.empty import EmptyOperator
   from airflow.sdk import DAG
   
   with DAG("probe", schedule=None, start_date=pendulum.datetime(2026, 1, 1, 
tz="UTC"), catchup=False):
       BashOperator(task_id="a", bash_command="exit 1", retries=0) >> 
EmptyOperator(task_id="b")
   ```
   
   With `airflow standalone` running (LocalExecutor, SQLite, examples off), 
trigger two runs through the API: `dated` with `"logical_date": 
"2026-10-01T00:00:00+00:00"`, then `manual` with `"logical_date": null`. Once 
both have failed (`a` failed, `b` upstream_failed), run:
   
   ```sh
   curl -s -X PATCH 
http://localhost:8080/api/v2/dags/probe/dagRuns/manual/taskInstances/a \
     -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
     -d '{"new_state":"success","include_future":true}'
   ```
   
   Result on 3.3.2 and main: the response is 200 and lists only `manual/a` as 
success, but the `dated` run also has `b` cleared and its state set to 
`queued`. Without `include_future`, or with it on the `dated` run, only the 
targeted run changes.
   
   ### What you think should happen instead?
   
   A run without a logical date has no past or future. The request should 
either be rejected with the same 400 as the clear route, or affect that run 
alone, as the state change itself already does.
   
   In `airflow-core/src/airflow/serialization/definitions/dag.py`, 
`SerializedDAG.set_task_instance_state` clears the downstream tasks with 
`start_date` (or `end_date`) set to the run's logical date; when that is 
`None`, no date bound is applied and the clear matches every run of the Dag. 
`set_task_group_state` has the same block, and the task-group route returns 500 
for the same request (`DagRun.logical_date >= None` in its lock query).
   
   ### Operating System
   
   macOS 26.2, Python 3.12 for 3.3.2; Linux/Breeze, Python 3.11 for main.
   
   ### Deployment
   
   Virtualenv installation
   
   ### Versions of Apache Airflow Providers
   
   `apache-airflow-providers-standard==1.19.0`
   
   ### Anything else?
   
   No duplicate found in open/closed issue and PR searches for 
`include_future`, `include_past` and `set_task_instance_state`. #46804/#47036 
cover the clear route only; #67707 and #63697 are about downstream tasks in the 
same run.
   
   ### Are you willing to submit PR?
   
   No. I am reporting the bug and am not planning to submit a PR.
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md).
   
   ---
   Drafted-by: Claude Code 2.1.303 (Claude Fable 5.1); reviewed by 
@luc-pimentel before posting
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to