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

kaxil 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 f05c32e10e1 Lower severity of handled XCom misses (#73198)
f05c32e10e1 is described below

commit f05c32e10e1a37289175ebd4c61b647252737960
Author: AxelRay <[email protected]>
AuthorDate: Thu Nov 5 05:02:15 2026 +0700

    Lower severity of handled XCom misses (#73198)
    
    * Lower log level for handled XCom misses
    
    * Log handled XCom misses at debug level
    
    LazyXComIterator reads offsets until the server returns 404, so every
    iteration over a mapped upstream ends in a handled miss. Log both XCom
    not-found branches at debug, like the Connection and Variable lookups.
    
    Move the new tests to httpx2, use the server's real 404 body, and name
    them after the fallback they cover.
    
    ---------
    
    Co-authored-by: Kaxil Naik <[email protected]>
---
 task-sdk/src/airflow/sdk/api/client.py     |  4 +--
 task-sdk/tests/task_sdk/api/test_client.py | 50 ++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/task-sdk/src/airflow/sdk/api/client.py 
b/task-sdk/src/airflow/sdk/api/client.py
index bdf5ba34bff..2638a2a697c 100644
--- a/task-sdk/src/airflow/sdk/api/client.py
+++ b/task-sdk/src/airflow/sdk/api/client.py
@@ -659,7 +659,7 @@ class XComOperations:
             resp = self.client.get(f"xcoms/{dag_id}/{run_id}/{task_id}/{key}", 
params=params)
         except ServerResponseError as e:
             if e.response.status_code == HTTPStatus.NOT_FOUND:
-                log.error(
+                log.debug(
                     "XCom not found",
                     dag_id=dag_id,
                     run_id=run_id,
@@ -740,7 +740,7 @@ class XComOperations:
             )
         except ServerResponseError as e:
             if e.response.status_code == HTTPStatus.NOT_FOUND:
-                log.error(
+                log.debug(
                     "XCom not found",
                     dag_id=dag_id,
                     run_id=run_id,
diff --git a/task-sdk/tests/task_sdk/api/test_client.py 
b/task-sdk/tests/task_sdk/api/test_client.py
index 9b23b65c153..a0bd43dffbb 100644
--- a/task-sdk/tests/task_sdk/api/test_client.py
+++ b/task-sdk/tests/task_sdk/api/test_client.py
@@ -1163,6 +1163,56 @@ class TestXCOMOperations:
                     key="key",
                 )
 
+    def test_xcom_get_404_returns_none_value(self):
+        def handle_request(request: httpx2.Request) -> httpx2.Response:
+            if request.url.path == "/xcoms/dag_id/run_id/task_id/key":
+                return httpx2.Response(
+                    status_code=404,
+                    json={"detail": {"reason": "not_found", "message": "XCom 
not found"}},
+                )
+            return httpx2.Response(status_code=400, json={"detail": "Bad 
Request"})
+
+        client = make_client(transport=httpx2.MockTransport(handle_request))
+
+        result = client.xcoms.get(
+            dag_id="dag_id",
+            run_id="run_id",
+            task_id="task_id",
+            key="key",
+        )
+
+        assert result == XComResponse(key="key", value=None)
+
+    def test_xcom_get_sequence_item_404_returns_not_found_error(self):
+        def handle_request(request: httpx2.Request) -> httpx2.Response:
+            if request.url.path == "/xcoms/dag_id/run_id/task_id/key/item/2":
+                return httpx2.Response(
+                    status_code=404,
+                    json={"detail": {"reason": "not_found", "message": "XCom 
not found"}},
+                )
+            return httpx2.Response(status_code=400, json={"detail": "Bad 
Request"})
+
+        client = make_client(transport=httpx2.MockTransport(handle_request))
+
+        result = client.xcoms.get_sequence_item(
+            dag_id="dag_id",
+            run_id="run_id",
+            task_id="task_id",
+            key="key",
+            offset=2,
+        )
+
+        assert result == ErrorResponse(
+            error=ErrorType.XCOM_NOT_FOUND,
+            detail={
+                "dag_id": "dag_id",
+                "run_id": "run_id",
+                "task_id": "task_id",
+                "key": "key",
+                "offset": 2,
+            },
+        )
+
     @pytest.mark.parametrize(
         "values",
         [

Reply via email to