Skip to content

Conversation

@kaxil
Copy link
Member

@kaxil kaxil commented Sep 17, 2025

Remove BaseOperator import from version_compat.py to prevent circular import during XCom backend resolution. The import was causing startup failures for scheduler and triggerer when XComObjectStorageBackend was configured as the XCom backend.

Move BaseOperator import directly to file_transfer.py where it's needed, maintaining compatibility with both Airflow 2.x and 3.x while avoiding the circular dependency chain that was introduced in PR #52443.

For use with Airflow 2.x, this is what was causing Circular import:

XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄

Fixes #55803


To Reproduce:

❯ docker run -it -v ./dist:/dist -v ~/.cache/uv:/root/.cache/uv -p 8080:8080 apache/airflow:2.11.0 bash

airflow@895deb8d01b2:/opt/airflow$ uv pip install apache-airflow-providers-common-io==1.6.2
Using Python 3.12.10 environment at: /home/airflow/.local
Resolved 136 packages in 961ms
Prepared 1 package in 20ms
Uninstalled 1 package in 40ms
Installed 1 package in 1ms
 - apache-airflow-providers-common-io==1.6.0
 + apache-airflow-providers-common-io==1.6.2
airflow@895deb8d01b2:/opt/airflow$ uvx ipython
Installed 16 packages in 38ms
/tmp/.cache/uv/archive-v0/REzCZt_aez_Mr3pLZsLJ1/lib/python3.12/site-packages/IPython/core/interactiveshell.py:975: UserWarning: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
  warn(
Python 3.12.10 (main, May 10 2025, 02:07:43) [GCC 12.2.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 9.5.0 -- An enhanced Interactive Python. Type '?' for help.
Tip: IPython 9.0+ has hooks to integrate AI/LLM completions.

In [1]: import os
   ...: os.environ['AIRFLOW__CORE__XCOM_BACKEND'] = 'airflow.providers.common.io.xcom.backend.XComObjectStorageBackend'
   ...: os.environ['AIRFLOW__COMMON_IO__XCOM_OBJECTSTORAGE_PATH'] = 'file:///tmp/xcom'
   ...: os.environ['AIRFLOW__COMMON_IO__XCOM_OBJECTSTORAGE_THRESHOLD'] = '100'

In [2]: import airflow.models

In [3]: import airflow.models.XCom
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[3], line 1
----> 1 import airflow.models.XCom

ModuleNotFoundError: No module named 'airflow.models.XCom'

In [4]: from airflow.models.xcom import XCom
/home/airflow/.local/lib/python3.12/site-packages/airflow/metrics/base_stats_logger.py:22 RemovedInAirflow3Warning: Timer and timing metrics publish in seconds were deprecated. It is enabled by default from Airflow 3 onwards. Enable timer_unit_consistency to publish all the timer and timing metrics in milliseconds.
[2025-09-17T20:52:50.610+0000] {configuration.py:1348} WARNING - cannot import name 'XCom' from partially initialized module 'airflow.models.xcom' (most likely due to a circular import) (/home/airflow/.local/lib/python3.12/site-packages/airflow/models/xcom.py)
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
File ~/.local/lib/python3.12/site-packages/airflow/configuration.py:1346, in AirflowConfigParser.getimport(self, section, key, **kwargs)
   1345 try:
-> 1346     return import_string(full_qualified_path)
   1347 except ImportError as e:

File ~/.local/lib/python3.12/site-packages/airflow/utils/module_loading.py:39, in import_string(dotted_path)
     37     raise ImportError(f"{dotted_path} doesn't look like a module path")
---> 39 module = import_module(module_path)
     41 try:

File /usr/local/lib/python3.12/importlib/__init__.py:90, in import_module(name, package)
     89         level += 1
---> 90 return _bootstrap._gcd_import(name[level:], package, level)

File <frozen importlib._bootstrap>:1387, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1360, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1331, in _find_and_load_unlocked(name, import_)

File <frozen importlib._bootstrap>:935, in _load_unlocked(spec)

File <frozen importlib._bootstrap_external>:999, in exec_module(self, module)

File <frozen importlib._bootstrap>:488, in _call_with_frames_removed(f, *args, **kwds)

File ~/.local/lib/python3.12/site-packages/airflow/providers/common/io/xcom/backend.py:30
     29 from airflow.configuration import conf
---> 30 from airflow.providers.common.io.version_compat import AIRFLOW_V_3_0_PLUS
     31 from airflow.utils.json import XComDecoder, XComEncoder

File ~/.local/lib/python3.12/site-packages/airflow/providers/common/io/version_compat.py:40
     39 else:
---> 40     from airflow.models import BaseOperator
     42 __all__ = [
     43     "AIRFLOW_V_3_0_PLUS",
     44     "BaseOperator",
     45 ]

File ~/.local/lib/python3.12/site-packages/airflow/models/__init__.py:79, in __getattr__(name)
     77     from airflow.utils.module_loading import import_string
---> 79     val = import_string(f"{path}.{name}")
     80 else:

File ~/.local/lib/python3.12/site-packages/airflow/utils/module_loading.py:39, in import_string(dotted_path)
     37     raise ImportError(f"{dotted_path} doesn't look like a module path")
---> 39 module = import_module(module_path)
     41 try:

File /usr/local/lib/python3.12/importlib/__init__.py:90, in import_module(name, package)
     89         level += 1
---> 90 return _bootstrap._gcd_import(name[level:], package, level)

File ~/.local/lib/python3.12/site-packages/airflow/models/baseoperator.py:83
     82 from airflow.models.base import _sentinel
---> 83 from airflow.models.mappedoperator import OperatorPartial, validate_mapping_kwargs
     84 from airflow.models.param import ParamsDict

File ~/.local/lib/python3.12/site-packages/airflow/models/mappedoperator.py:54
     53 from airflow.ti_deps.deps.mapped_task_expanded import MappedTaskIsExpanded
---> 54 from airflow.triggers.base import StartTriggerArgs
     55 from airflow.typing_compat import Literal

File ~/.local/lib/python3.12/site-packages/airflow/triggers/base.py:27
     26 from airflow.callbacks.database_callback_sink import DatabaseCallbackSink
---> 27 from airflow.models.taskinstance import SimpleTaskInstance
     28 from airflow.utils.log.logging_mixin import LoggingMixin

File ~/.local/lib/python3.12/site-packages/airflow/models/taskinstance.py:104
    103 from airflow.models.taskreschedule import TaskReschedule
--> 104 from airflow.models.xcom import LazyXComSelectSequence, XCom
    105 from airflow.plugins_manager import integrate_macros_plugins

ImportError: cannot import name 'XCom' from partially initialized module 'airflow.models.xcom' (most likely due to a circular import) (/home/airflow/.local/lib/python3.12/site-packages/airflow/models/xcom.py)

During handling of the above exception, another exception occurred:

AirflowConfigException                    Traceback (most recent call last)
Cell In[4], line 1
----> 1 from airflow.models.xcom import XCom

File ~/.local/lib/python3.12/site-packages/airflow/models/xcom.py:815
    813     XCom = BaseXCom  # Hack to avoid Mypy "Variable 'XCom' is not valid as a type".
    814 else:
--> 815     XCom = resolve_xcom_backend()

File ~/.local/lib/python3.12/site-packages/airflow/models/xcom.py:798, in resolve_xcom_backend()
    791 def resolve_xcom_backend() -> type[BaseXCom]:
    792     """
    793     Resolve custom XCom class.
    794
    795     Confirm that custom XCom class extends the BaseXCom.
    796     Compare the function signature of the custom XCom serialize_value to the base XCom serialize_value.
    797     """
--> 798     clazz = conf.getimport("core", "xcom_backend", fallback=f"airflow.models.xcom.{BaseXCom.__name__}")
    799     if not clazz:
    800         return BaseXCom

File ~/.local/lib/python3.12/site-packages/airflow/configuration.py:1349, in AirflowConfigParser.getimport(self, section, key, **kwargs)
   1347 except ImportError as e:
   1348     log.warning(e)
-> 1349     raise AirflowConfigException(
   1350         f'The object could not be loaded. Please check "{key}" key in "{section}" section. '
   1351         f'Current value: "{full_qualified_path}".'
   1352     )

AirflowConfigException: The object could not be loaded. Please check "xcom_backend" key in "core" section. Current value: "airflow.providers.common.io.xcom.backend.XComObjectStorageBackend".


^ Add meaningful description above
Read the Pull Request Guidelines for more information.
In case of fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in a newsfragment file, named {pr_number}.significant.rst or {issue_number}.significant.rst, in airflow-core/newsfragments.

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
@kaxil kaxil merged commit 8d891bb into apache:main Sep 17, 2025
76 checks passed
@kaxil kaxil deleted the fix-circular-import-xcom branch September 17, 2025 20:54
Copy link
Contributor

@amoghrajesh amoghrajesh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn!

abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Sep 30, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 1, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 2, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 3, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 4, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 5, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 5, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 7, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 8, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 9, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 10, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 11, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 12, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 14, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 15, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 17, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
abdulrahman305 bot pushed a commit to abdulrahman305/airflow that referenced this pull request Oct 19, 2025
…5805)

Remove ``BaseOperator`` import from ``version_compat.py`` to prevent circular
import during ``XCom`` backend resolution. The import was causing startup
failures for scheduler and triggerer when XComObjectStorageBackend
was configured as the XCom backend.

Move ``BaseOperator`` import directly to `file_transfer.py` where it's needed,
maintaining compatibility with both Airflow 2.x and 3.x while avoiding
the circular dependency chain that was introduced in PR apache#52443.

For use with Airflow 2.x, this is what was causing Circular import:

```
XCom Backend Resolution
    ↓
airflow.providers.common.io.xcom.backend
    ↓
airflow.providers.common.io.version_compat (imports BaseOperator at module level)
    ↓
airflow.models.BaseOperator (or airflow.sdk.BaseOperator)
    ↓
airflow.models.mappedoperator (BaseOperator imports this)
    ↓
airflow.triggers.base (MappedOperator imports this)
    ↓
airflow.models.taskinstance (triggers.base imports SimpleTaskInstance)
    ↓
airflow.models.xcom (TaskInstance imports XCom)
    ↓
resolve_xcom_backend() (tries to load XCom backend again)
    ↓
CIRCULAR IMPORT! 🔄
```

Fixes apache#55803
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to use XComObjectStorageBackend with apache-airflow-providers-common-io==1.6.2

3 participants