You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by mo...@apache.org on 2026/04/22 17:36:42 UTC
(airflow) branch main updated: Fix DetachedInstanceError in OpenLineage listener by using safe_getattr (#65579)
This is an automated email from the ASF dual-hosted git repository.
mobuchowski 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 052d27f4179 Fix DetachedInstanceError in OpenLineage listener by using safe_getattr (#65579)
052d27f4179 is described below
commit 052d27f4179d7d35589f526a01b48aa50f7e2845
Author: Subham <su...@gmail.com>
AuthorDate: Wed Apr 22 23:06:33 2026 +0530
Fix DetachedInstanceError in OpenLineage listener by using safe_getattr (#65579)
---
.../src/airflow/providers/openlineage/utils/utils.py | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/providers/openlineage/src/airflow/providers/openlineage/utils/utils.py b/providers/openlineage/src/airflow/providers/openlineage/utils/utils.py
index 78441eaddf7..1b49155001a 100644
--- a/providers/openlineage/src/airflow/providers/openlineage/utils/utils.py
+++ b/providers/openlineage/src/airflow/providers/openlineage/utils/utils.py
@@ -30,6 +30,7 @@ import attrs
from openlineage.client.facet_v2 import job_dependencies_run, parent_run
from openlineage.client.utils import RedactMixin
from openlineage.client.uuid import generate_static_uuid
+from sqlalchemy.orm.exc import DetachedInstanceError
from airflow import __version__ as AIRFLOW_VERSION
from airflow.models import DagRun, TaskInstance, TaskReschedule
@@ -576,6 +577,14 @@ if not AIRFLOW_V_3_0_PLUS:
)
+def safe_getattr(obj: Any, attr: str, default: Any = None) -> Any:
+ """Get attribute from object, returning default if DetachedInstanceError is raised."""
+ try:
+ return getattr(obj, attr, default)
+ except DetachedInstanceError:
+ return default
+
+
class InfoJsonEncodable(dict):
"""
Airflow objects might not be json-encodable overall.
@@ -755,7 +764,7 @@ class DagRunInfo(InfoJsonEncodable):
]
casts = {
- "note": lambda dagrun: getattr(dagrun, "note", None) if AIRFLOW_V_3_2_PLUS else None,
+ "note": lambda dagrun: safe_getattr(dagrun, "note") if AIRFLOW_V_3_2_PLUS else None,
"duration": lambda dagrun: DagRunInfo.duration(dagrun),
"dag_bundle_name": lambda dagrun: DagRunInfo.dag_version_info(dagrun, "bundle_name"),
"dag_bundle_version": lambda dagrun: DagRunInfo.dag_version_info(dagrun, "bundle_version"),
@@ -781,7 +790,7 @@ class DagRunInfo(InfoJsonEncodable):
"""
try:
# AF2 DagRun and AF3 DagRun SDK model (on worker) do not have this information
- deadlines = getattr(dagrun, "deadlines", None)
+ deadlines = safe_getattr(dagrun, "deadlines")
if not deadlines:
return None
except Exception as err:
@@ -800,7 +809,7 @@ class DagRunInfo(InfoJsonEncodable):
# deadline_alert is a lazy-loaded ORM relationship that may
# trigger a DB query; keep it isolated so a detached-session
# error doesn't discard the rest of the deadline info.
- if alert := getattr(d, "deadline_alert", None):
+ if alert := safe_getattr(d, "deadline_alert"):
info.update(
{
k: v
@@ -820,9 +829,10 @@ class DagRunInfo(InfoJsonEncodable):
def dag_version_info(cls, dagrun: DagRun, key: str) -> str | int | None:
"""Extract deg version info for given key, sourced from DagRun (on scheduler)."""
# AF2 DagRun and AF3 DagRun SDK model (on worker) do not have this information
- if not getattr(dagrun, "dag_versions", []):
+ dag_versions = safe_getattr(dagrun, "dag_versions", [])
+ if not dag_versions:
return None
- current_version = dagrun.dag_versions[-1]
+ current_version = dag_versions[-1]
if key == "bundle_name":
return current_version.bundle_name
if key == "bundle_version":