From 6636d7777fa83d110b79e71d3397ae05ce308eab Mon Sep 17 00:00:00 2001 From: fullsend-code <278716306+fullsend-ai-coder[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 13:52:58 +0000 Subject: [PATCH] fix(#3109): catch httpx.HTTPStatusError in Watsonx model discovery WatsonxIAMAuth.raise_for_status() raises httpx.HTTPStatusError on IAM token exchange failures (401/403/5xx), which is not a subclass of openai.APIError. This escaped the except clause in _discover_models, propagating unwrapped instead of as ModelDiscoveryError. Widen the except tuple to (APIError, httpx.HTTPStatusError) so IAM failures are wrapped consistently with other discovery errors. Add a parametrized test case for httpx.HTTPStatusError to the existing test_discover_models_wraps_api_error test. Closes #3109 --- src/providers/inference/watsonx/provider.py | 3 ++- tests/unit/providers/inference/watsonx/test_provider.py | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/providers/inference/watsonx/provider.py b/src/providers/inference/watsonx/provider.py index 5ba4c6a9d..811d6d4ed 100644 --- a/src/providers/inference/watsonx/provider.py +++ b/src/providers/inference/watsonx/provider.py @@ -5,6 +5,7 @@ import asyncio from typing import TYPE_CHECKING, Any, Optional +import httpx from openai import APIError from pydantic_ai.embeddings import EmbeddingModel from pydantic_ai.embeddings.openai import OpenAIEmbeddingModel @@ -63,7 +64,7 @@ async def _discover_models(self) -> list[DiscoveredModel]: ), self._list_foundation_model_functions(), ) - except APIError as exc: + except (APIError, httpx.HTTPStatusError) as exc: raise ModelDiscoveryError(self.provider_id) from exc discovered: list[DiscoveredModel] = [] diff --git a/tests/unit/providers/inference/watsonx/test_provider.py b/tests/unit/providers/inference/watsonx/test_provider.py index 71367bc70..ba7c2fc13 100644 --- a/tests/unit/providers/inference/watsonx/test_provider.py +++ b/tests/unit/providers/inference/watsonx/test_provider.py @@ -128,8 +128,13 @@ async def test_discover_models_keeps_chat_and_embedding_only( ), body=None, ), + httpx.HTTPStatusError( + "IAM token exchange failed", + request=httpx.Request("POST", "https://iam.cloud.ibm.com/identity/token"), + response=httpx.Response(401), + ), ], - ids=["connection-error", "authentication-error"], + ids=["connection-error", "authentication-error", "iam-http-status-error"], ) async def test_discover_models_wraps_api_error( provider: WatsonxInferenceProvider,