Skip to content

Commit 4afb546

Browse files
awalker4claude
andcommitted
fix(ibm-watsonx-s3): fail fast on precheck and guard bearer token JSON parsing
- Add optional max_retries param to get_catalog() so callers can cap retries - Use max_retries=1 in precheck() to surface connection errors immediately instead of blocking through the full exponential-backoff window - Move response.json() inside try/except in generate_bearer_token() so non-JSON IAM responses are caught and wrapped rather than raised raw Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 96ab3a5 commit 4afb546

3 files changed

Lines changed: 13 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [1.4.15]
2+
3+
* **fix(ibm-watsonx-s3): fail fast on precheck and guard bearer token JSON parsing**
4+
15
## [1.4.14]
26

37
* **fix(teradata): enable Unicode Pass Through on session to prevent Error 6705 on non-BMP characters**

unstructured_ingest/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.4.14" # pragma: no cover
1+
__version__ = "1.4.15" # pragma: no cover

unstructured_ingest/processes/connectors/ibm_watsonx/ibm_watsonx_s3.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ def generate_bearer_token(self) -> dict[str, Any]:
132132
try:
133133
response = httpx.post(DEFAULT_IBM_CLOUD_AUTH_URL, headers=headers, data=data)
134134
response.raise_for_status()
135+
return response.json()
135136
except Exception as e:
136137
raise self.wrap_error(e)
137-
return response.json()
138138

139139
def get_catalog_config(self) -> dict[str, Any]:
140140
return {
@@ -155,7 +155,7 @@ def get_catalog_config(self) -> dict[str, Any]:
155155

156156
@requires_dependencies(["pyiceberg"], extras="ibm-watsonx-s3")
157157
@contextmanager
158-
def get_catalog(self) -> Generator["RestCatalog", None, None]:
158+
def get_catalog(self, max_retries: Optional[int] = None) -> Generator["RestCatalog", None, None]:
159159
from pyiceberg.catalog import load_catalog
160160
from pyiceberg.exceptions import RESTError
161161
from tenacity import (
@@ -166,9 +166,11 @@ def get_catalog(self) -> Generator["RestCatalog", None, None]:
166166
wait_exponential,
167167
)
168168

169+
retries = max_retries if max_retries is not None else self.max_retries_connection
170+
169171
# Retry connection in case of a connection error
170172
@retry(
171-
stop=stop_after_attempt(self.max_retries_connection),
173+
stop=stop_after_attempt(retries),
172174
wait=wait_exponential(exp_base=2, multiplier=1, min=2, max=10),
173175
retry=retry_if_exception_type(RESTError),
174176
before=before_log(logger, logging.DEBUG),
@@ -225,7 +227,9 @@ class IbmWatsonxUploader(SQLUploader):
225227
connector_type: str = CONNECTOR_TYPE
226228

227229
def precheck(self) -> None:
228-
with self.connection_config.get_catalog() as catalog:
230+
# Use max_retries=1 (no retries) during precheck so a transient provider error
231+
# surfaces quickly rather than blocking for the full exponential-backoff window.
232+
with self.connection_config.get_catalog(max_retries=1) as catalog:
229233
if not catalog.namespace_exists(self.upload_config.namespace):
230234
raise UserError(f"Namespace '{self.upload_config.namespace}' does not exist")
231235
if not catalog.table_exists(self.upload_config.table_identifier):

0 commit comments

Comments
 (0)