This is an automated email from the ASF dual-hosted git repository.

amoghrajesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 403a1ebaa77 Fix task run context crash when DagRun state is expired 
(#66339)
403a1ebaa77 is described below

commit 403a1ebaa77c05a398004e94106733bb35252954
Author: Amogh Desai <[email protected]>
AuthorDate: Mon May 4 15:47:32 2026 +0530

    Fix task run context crash when DagRun state is expired (#66339)
---
 .../execution_api/datamodels/taskinstance.py            |  7 +++++--
 .../tests/unit/cli/commands/test_task_command.py        | 17 +++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py 
b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py
index adef323565f..a0d97390801 100644
--- 
a/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py
+++ 
b/airflow-core/src/airflow/api_fastapi/execution_api/datamodels/taskinstance.py
@@ -338,8 +338,11 @@ class DagRun(StrictBaseModel):
         for field_name in cls.model_fields:
             if field_name in insp.dict:
                 values[field_name] = insp.dict[field_name]
-            elif field_name == "state" and "_state" in insp.dict:
-                values["state"] = insp.dict["_state"]
+            elif field_name == "state":
+                if "_state" in insp.dict:
+                    values["state"] = insp.dict["_state"]
+                elif not insp.detached and (state_val := data._state) is not 
None:
+                    values["state"] = state_val
 
         if "consumed_asset_events" not in values:
             values["consumed_asset_events"] = []
diff --git a/airflow-core/tests/unit/cli/commands/test_task_command.py 
b/airflow-core/tests/unit/cli/commands/test_task_command.py
index b66384d5ad4..f39a8409bc2 100644
--- a/airflow-core/tests/unit/cli/commands/test_task_command.py
+++ b/airflow-core/tests/unit/cli/commands/test_task_command.py
@@ -307,6 +307,23 @@ class TestCliTasks:
         with redirect_stdout(io.StringIO()):
             task_command.task_render(args)
 
+    @pytest.mark.db_test
+    def test_task_render_handles_expired_dagrun(self, dag_maker, session):
+        """Test that model_validate extracts state from an expired DagRun 
instance."""
+        from airflow.api_fastapi.execution_api.datamodels.taskinstance import 
DagRun as DagRunPydantic
+        from airflow.utils.state import DagRunState
+
+        with dag_maker(dag_id="test_expired", session=session):
+            pass
+
+        dr = dag_maker.create_dagrun(state=DagRunState.RUNNING)
+        session.commit()
+        # After commit, SQLAlchemy expires all attributes — _state is no 
longer in insp.dict
+        # but the instance is still attached, so direct access triggers a lazy 
reload.
+
+        pydantic_dr = DagRunPydantic.model_validate(dr)
+        assert pydantic_dr.state == DagRunState.RUNNING
+
     @pytest.mark.usefixtures("testing_dag_bundle")
     def test_mapped_task_render(self):
         """

Reply via email to