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

   ### Under which category would you file this issue?
   
   Airflow Core
   
   ### Apache Airflow version
   
   3.3.2; also reproduced on main on October 21, 2026 (3.4.0b2 has the same 
code).
   
   ### What happened and how to reproduce it?
   
   The metrics docs list the counter `previously_succeeded` ("Number of 
previously succeeded task instances"). Its only emit site is 
`TaskInstance._check_and_change_state_before_execution` in 
`airflow-core/src/airflow/models/taskinstance.py`, which nothing in Airflow 3 
calls: workers move a task to running through the `ti_run` Execution API route 
instead (#57818 noted the method has been unused since 3.0). The event the 
counter describes, a worker handed a task instance that already succeeded, now 
ends with `ti_run` answering 409 `invalid_state` with `previous_state: 
success`, and nothing is counted there. It is the same pattern as 
`task.queued_duration` (#63503, #66067), fixed by #67592.
   
   To see it: run `airflow standalone` (LocalExecutor, SQLite) with `[metrics] 
statsd_on = True` pointed at any StatsD listener, trigger a Dag with one 
`BashOperator` and let it succeed, then hand the finished task instance to the 
executor again:
   
   ```python
   # relaunch.py <dag_id> <task_id> <run_id>: replay the LocalExecutor's launch 
of a finished task instance
   import sys
   
   from sqlalchemy import select
   from sqlalchemy.orm import joinedload
   
   from airflow import settings
   from airflow.executors.base_executor import BaseExecutor
   from airflow.executors.local_executor import LocalExecutor
   from airflow.executors.workloads import ExecuteTask
   from airflow.models.taskinstance import TaskInstance as TI
   
   dag_id, task_id, run_id = sys.argv[1:4]
   ti = settings.Session().scalar(
       select(TI)
       .where(TI.dag_id == dag_id, TI.task_id == task_id, TI.run_id == run_id)
       .options(joinedload(TI.dag_run), joinedload(TI.dag_model))
   )
   BaseExecutor.run_workload(ExecuteTask.make(ti, 
generator=LocalExecutor().jwt_generator), subprocess_logs_to_stdout=True)
   ```
   
   Result on 3.3.2 and main: the supervisor logs `Server error detail: 
{'reason': 'invalid_state', 'message': 'TI was not in a state where it could be 
marked as running', 'previous_state': 'success'}` and the listener receives no 
`previously_succeeded` datagram. The first run of the same task delivers 
`ti.start`, `ti.finish.success`, `ti_successes`, `task.duration`, 
`task.scheduled_duration` and, on main, `task.queued_duration`, so the StatsD 
path itself works.
   
   ### What you think should happen instead?
   
   Either `ti_run` increments `previously_succeeded` when it refuses a start 
for a task instance whose previous state is success (next to where #67592 
re-emits `task.queued_duration`), or the counter is removed from the metrics 
registry and the docs, so dashboards and alerts built on it stop waiting for a 
metric that cannot arrive.
   
   ### 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 
`previously_succeeded`, `check_and_change_state_before_execution` and 
`emit_state_change_metric`. #67592 changes only the success branch of `ti_run`, 
so it neither introduced nor fixed this. The counter was last live in Airflow 
2, where `LocalTaskJobRunner` called `check_and_change_state_before_execution` 
before running the task.
   
   ### 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.307 (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