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

vincbeck 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 80e870d3dfa Fix SageMakerTransformOperator succeeding on a failed 
deferred job (#69042)
80e870d3dfa is described below

commit 80e870d3dfa3a04a2dfa5693872f2a5e3dcec8d2
Author: Steve Ahn <[email protected]>
AuthorDate: Mon Jun 29 06:07:25 2026 -0700

    Fix SageMakerTransformOperator succeeding on a failed deferred job (#69042)
    
    A deferred SageMaker transform job that fails during the wait was reported 
as a
    successful task: execute_complete did not check the trigger event status, 
so the
    failed job's description was pushed as the result and downstream tasks ran 
against
    missing or invalid transform output with no error surfaced. Since the 
trigger was
    migrated to AwsBaseWaiterTrigger it yields a {"status": "error"} event on 
failure
    instead of raising, so the status guard that every sibling SageMaker 
operator has
    became load-bearing here too.
---
 .../providers/amazon/aws/operators/sagemaker.py    |  3 +++
 .../aws/operators/test_sagemaker_transform.py      | 27 ++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git 
a/providers/amazon/src/airflow/providers/amazon/aws/operators/sagemaker.py 
b/providers/amazon/src/airflow/providers/amazon/aws/operators/sagemaker.py
index e23db37ae2d..21fdaa6b988 100644
--- a/providers/amazon/src/airflow/providers/amazon/aws/operators/sagemaker.py
+++ b/providers/amazon/src/airflow/providers/amazon/aws/operators/sagemaker.py
@@ -944,6 +944,9 @@ class SageMakerTransformOperator(SageMakerBaseOperator):
     def execute_complete(self, context: Context, event: dict[str, Any] | None 
= None) -> dict[str, dict]:
         validated_event = validate_execute_complete_event(event)
 
+        if validated_event["status"] != "success":
+            raise RuntimeError(f"Error while running transform job: 
{validated_event}")
+
         self.log.info("SageMaker job %s completed.", 
validated_event["job_name"])
         return self.serialize_result(validated_event["job_name"])
 
diff --git 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
index 40c86115c48..de8ed7841e8 100644
--- 
a/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
+++ 
b/providers/amazon/tests/unit/amazon/aws/operators/test_sagemaker_transform.py
@@ -341,6 +341,33 @@ class TestSageMakerTransformOperator:
             self.sagemaker.execute(context=None)
         assert not mock_defer.called
 
+    @mock.patch.object(sagemaker, "serialize", return_value="")
+    @mock.patch.object(SageMakerHook, "describe_model", 
return_value={"ModelName": "model_name"})
+    @mock.patch.object(
+        SageMakerHook,
+        "describe_transform_job",
+        return_value={
+            "ModelName": "model_name",
+            "TransformJobStatus": "Failed",
+            "FailureReason": "it failed",
+        },
+    )
+    def test_execute_complete_raises_when_job_failed_during_deferred_wait(
+        self, mock_describe_transform_job, mock_describe_model, mock_serialize
+    ):
+        # When the transform job fails during the deferred wait, the trigger 
(an
+        # AwsBaseWaiterTrigger) yields {"status": "error", ...} instead of 
raising, so
+        # execute_complete must reject a non-success status rather than report 
the task as
+        # successful — matching every other SageMaker operator's 
execute_complete.
+        event = {
+            "status": "error",
+            "message": "Error while waiting for transform job: terminal 
failure",
+            "job_name": "job_name",
+        }
+
+        with pytest.raises(RuntimeError, match="Error while running transform 
job"):
+            self.sagemaker.execute_complete(context=None, event=event)
+
     
@mock.patch("airflow.providers.amazon.aws.operators.sagemaker.SageMakerTransformOperator.defer")
     @mock.patch.object(SageMakerHook, "describe_model")
     @mock.patch.object(

Reply via email to