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

potiuk 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 4dd620f48d8 Fix XCom slice endpoint for crossed bounds (#72584)
4dd620f48d8 is described below

commit 4dd620f48d80806b7ae12a3c04f11bc678e54721
Author: Vincent Hsiao <[email protected]>
AuthorDate: Wed Sep 9 09:59:07 2026 +0800

    Fix XCom slice endpoint for crossed bounds (#72584)
---
 .../src/airflow/api_fastapi/execution_api/routes/xcoms.py  | 14 ++++++++++----
 .../api_fastapi/execution_api/versions/head/test_xcoms.py  |  4 ++++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py 
b/airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py
index 2e1736a5290..4dd7f6818fc 100644
--- a/airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py
+++ b/airflow-core/src/airflow/api_fastapi/execution_api/routes/xcoms.py
@@ -178,6 +178,12 @@ class GetXComSliceFilterParams(BaseModel):
     include_prior_dates: bool = False
 
 
+def _get_sliced_query_or_empty(query: Select, low: int, high: int) -> Select:
+    if high <= low:
+        return query.limit(0)
+    return query.slice(low, high)
+
+
 @router.get(
     "/{dag_id}/{run_id}/{task_id}/{key:path}/slice",
     description="Get XCom values from a mapped task by sequence slice",
@@ -235,9 +241,9 @@ def get_mapped_xcom_by_slice(
             if stop < 0:
                 stop += get_query_count(query, session=session)
             if step >= 0:
-                query = query.slice(start, stop)
+                query = _get_sliced_query_or_empty(query, start, stop)
             else:
-                query = query.slice(stop + 1, start + 1)
+                query = _get_sliced_query_or_empty(query, stop + 1, start + 1)
     else:
         query = query.order_by(XComModel.map_index.desc())
         step = -step
@@ -250,9 +256,9 @@ def get_mapped_xcom_by_slice(
             if stop >= 0:
                 stop -= get_query_count(query, session=session)
             if step > 0:
-                query = query.slice(-1 - start, -1 - stop)
+                query = _get_sliced_query_or_empty(query, -1 - start, -1 - 
stop)
             else:
-                query = query.slice(-stop, -start)
+                query = _get_sliced_query_or_empty(query, -stop, -start)
 
     values = [row.value for row in 
session.execute(query.with_only_columns(XComModel.value)).all()]
     if step != 1:
diff --git 
a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_xcoms.py 
b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_xcoms.py
index 0b424dedc5d..64ddba31fc0 100644
--- 
a/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_xcoms.py
+++ 
b/airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_xcoms.py
@@ -232,6 +232,10 @@ class TestXComsGetEndpoint:
             pytest.param(slice(1, None, None), id="1:"),
             pytest.param(slice(2, None, -1), id="2::-1"),
             pytest.param(slice(1, 2, None), id="1:2"),
+            pytest.param(slice(2, 1, None), id="2:1"),
+            pytest.param(slice(1, -1, -1), id="1:-1:-1"),
+            pytest.param(slice(-1, -2, None), id="-1:-2"),
+            pytest.param(slice(-3, -1, -1), id="-3:-1:-1"),
             pytest.param(slice(2, 1, -1), id="2:1:-1"),
             pytest.param(slice(1, -1, None), id="1:-1"),
             pytest.param(slice(2, -2, -1), id="2:-2:-1"),

Reply via email to