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

amoghrajesh 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 f6225620e23 Include last error cause in Databricks API when retry is 
exhausted (#69238)
f6225620e23 is described below

commit f6225620e238c817dc8008c46fdec9eecc164664
Author: Amogh Desai <[email protected]>
AuthorDate: Mon Jul 6 14:29:59 2026 +0530

    Include last error cause in Databricks API when retry is exhausted (#69238)
---
 .../providers/databricks/hooks/databricks_base.py  | 37 +++++++++++++++++-----
 .../unit/databricks/hooks/test_databricks_base.py  |  5 ++-
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git 
a/providers/databricks/src/airflow/providers/databricks/hooks/databricks_base.py
 
b/providers/databricks/src/airflow/providers/databricks/hooks/databricks_base.py
index d66122063b2..c90d10cf69a 100644
--- 
a/providers/databricks/src/airflow/providers/databricks/hooks/databricks_base.py
+++ 
b/providers/databricks/src/airflow/providers/databricks/hooks/databricks_base.py
@@ -92,6 +92,15 @@ class DatabricksProxyConfigurationError(AirflowException):
     """Raised when Databricks connection proxy configuration is invalid."""
 
 
+def _describe_last_retry_error(retry_error: RetryError) -> str:
+    """Best-effort description of a RetryError last exception, some exceptions 
raise from __str__ when partially initialized."""
+    last_exc = retry_error.last_attempt.exception()
+    try:
+        return str(last_exc)
+    except Exception:
+        return repr(last_exc)
+
+
 class BaseDatabricksHook(BaseHook):
     """
     Base for interaction with Databricks.
@@ -325,8 +334,11 @@ class BaseDatabricksHook(BaseHook):
                     self._is_oauth_token_valid(jsn)
                     self.oauth_tokens[resource] = jsn
                     break
-        except RetryError:
-            raise AirflowException(f"API requests to Databricks failed 
{self.retry_limit} times. Giving up.")
+        except RetryError as e:
+            raise AirflowException(
+                f"API requests to Databricks failed {self.retry_limit} times "
+                f"(last error: {_describe_last_retry_error(e)}). Giving up."
+            ) from e
         except requests_exceptions.HTTPError as e:
             msg = f"Response: {e.response.content.decode()}, Status Code: 
{e.response.status_code}"
             raise AirflowException(msg)
@@ -363,8 +375,11 @@ class BaseDatabricksHook(BaseHook):
                     self._is_oauth_token_valid(jsn)
                     self.oauth_tokens[resource] = jsn
                     break
-        except RetryError:
-            raise AirflowException(f"API requests to Databricks failed 
{self.retry_limit} times. Giving up.")
+        except RetryError as e:
+            raise AirflowException(
+                f"API requests to Databricks failed {self.retry_limit} times "
+                f"(last error: {_describe_last_retry_error(e)}). Giving up."
+            ) from e
         except requests_exceptions.HTTPError as e:
             msg = f"Response: {e.response.content.decode()}, Status Code: 
{e.response.status_code}"
             raise AirflowException(msg)
@@ -1213,8 +1228,11 @@ class BaseDatabricksHook(BaseHook):
                     self.log.debug("Response text: %s", response.text)
                     response.raise_for_status()
                     return response.json()
-        except RetryError:
-            raise AirflowException(f"API requests to Databricks failed 
{self.retry_limit} times. Giving up.")
+        except RetryError as e:
+            raise AirflowException(
+                f"API requests to Databricks failed {self.retry_limit} times "
+                f"(last error: {_describe_last_retry_error(e)}). Giving up."
+            ) from e
         except requests_exceptions.HTTPError as e:
             if wrap_http_errors:
                 msg = f"Response: {e.response.content.decode()}, Status Code: 
{e.response.status_code}"
@@ -1277,8 +1295,11 @@ class BaseDatabricksHook(BaseHook):
                         self.log.debug("Response text: %s", response.text)
                         response.raise_for_status()
                         return await response.json()
-        except RetryError:
-            raise AirflowException(f"API requests to Databricks failed 
{self.retry_limit} times. Giving up.")
+        except RetryError as e:
+            raise AirflowException(
+                f"API requests to Databricks failed {self.retry_limit} times "
+                f"(last error: {_describe_last_retry_error(e)}). Giving up."
+            ) from e
         except aiohttp.ClientResponseError as err:
             raise DatabricksApiError(
                 f"Response: {err.message}, Status Code: {err.status}", 
http_status_code=err.status
diff --git 
a/providers/databricks/tests/unit/databricks/hooks/test_databricks_base.py 
b/providers/databricks/tests/unit/databricks/hooks/test_databricks_base.py
index 393107497d7..2c976312811 100644
--- a/providers/databricks/tests/unit/databricks/hooks/test_databricks_base.py
+++ b/providers/databricks/tests/unit/databricks/hooks/test_databricks_base.py
@@ -238,7 +238,10 @@ class TestBaseDatabricksHook:
         hook.user_agent_header = {"User-Agent": "test-agent"}
         resource = ""
 
-        with pytest.raises(AirflowException, match="API requests to Databricks 
failed 2 times. Giving up."):
+        with pytest.raises(
+            AirflowException,
+            match=r"API requests to Databricks failed 2 times \(last error: 
Connection failed\)\. Giving up\.",
+        ):
             hook._get_sp_token(resource)
 
     @pytest.mark.asyncio

Reply via email to