Skip to content

Commit 1643a62

Browse files
authored
fix: openai repsonses api error handling (#1931)
1 parent 83ff4e0 commit 1643a62

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

src/strands/models/openai_responses.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,14 @@ async def stream(
294294
if hasattr(event, "response") and hasattr(event.response, "usage"):
295295
final_usage = event.response.usage
296296
break
297-
except openai.BadRequestError as e:
297+
except openai.APIError as e:
298298
if hasattr(e, "code") and e.code == "context_length_exceeded":
299299
logger.warning(_CONTEXT_WINDOW_OVERFLOW_MSG)
300300
raise ContextWindowOverflowException(str(e)) from e
301+
if isinstance(e, openai.RateLimitError):
302+
logger.warning(_RATE_LIMIT_MSG)
303+
raise ModelThrottledException(str(e)) from e
301304
raise
302-
except openai.RateLimitError as e:
303-
logger.warning(_RATE_LIMIT_MSG)
304-
raise ModelThrottledException(str(e)) from e
305305

306306
# Close current content block if we had any
307307
if data_type:

tests/strands/models/test_openai_responses.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,26 @@ async def test_stream_context_overflow_exception(openai_client, model, messages)
653653
assert exc_info.value.__cause__ == mock_error
654654

655655

656+
@pytest.mark.asyncio
657+
async def test_stream_context_overflow_exception_api_error_type(openai_client, model, messages):
658+
"""Test that OpenAI context overflow errors are properly converted to ContextWindowOverflowException."""
659+
mock_error = openai.APIError(
660+
message="This model's maximum context length is 4096 tokens.",
661+
request=unittest.mock.MagicMock(),
662+
body={"error": {"code": "context_length_exceeded"}},
663+
)
664+
mock_error.code = "context_length_exceeded"
665+
666+
openai_client.responses.create.side_effect = mock_error
667+
668+
with pytest.raises(ContextWindowOverflowException) as exc_info:
669+
async for _ in model.stream(messages):
670+
pass
671+
672+
assert "maximum context length" in str(exc_info.value)
673+
assert exc_info.value.__cause__ == mock_error
674+
675+
656676
@pytest.mark.asyncio
657677
async def test_stream_rate_limit_as_throttle(openai_client, model, messages):
658678
"""Test that rate limit errors are converted to ModelThrottledException."""

tests_integ/models/test_model_openai.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,16 +225,15 @@ def _rate_limit_params():
225225
return params
226226

227227

228-
@pytest.mark.parametrize("model_class,model_id", _rate_limit_params())
229-
def test_rate_limit_throttling_integration_no_retries(model_class, model_id):
228+
def test_rate_limit_throttling_integration_no_retries():
230229
"""Integration test for rate limit handling with retries disabled.
231230
232231
This test verifies that when a request exceeds OpenAI's rate limits,
233232
the model properly raises a ModelThrottledException. We disable retries
234233
to avoid waiting for the exponential backoff during testing.
235234
"""
236-
model = model_class(
237-
model_id=model_id,
235+
model = OpenAIModel(
236+
model_id="gpt-4o",
238237
client_args={
239238
"api_key": os.getenv("OPENAI_API_KEY"),
240239
},

0 commit comments

Comments
 (0)