From 50ab150fa6189385ca724a9ba7b79ca34e765a98 Mon Sep 17 00:00:00 2001 From: Kent Date: Sat, 6 Jun 2026 00:43:19 +0800 Subject: [PATCH] fix(bedrock_mantle): catch specific credential errors, not all BotoCoreError, so STS transport failures are not masked --- .../responses/transformation.py | 14 ++++++- ...bedrock_mantle_responses_transformation.py | 37 ++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/litellm/llms/bedrock_mantle/responses/transformation.py b/litellm/llms/bedrock_mantle/responses/transformation.py index e1b12d03a11..df219091074 100644 --- a/litellm/llms/bedrock_mantle/responses/transformation.py +++ b/litellm/llms/bedrock_mantle/responses/transformation.py @@ -16,7 +16,12 @@ BaseAWSLLM._sign_request after the request body is finalized. import re from typing import Optional, Tuple -from botocore.exceptions import BotoCoreError +from botocore.exceptions import ( + CredentialRetrievalError, + NoCredentialsError, + PartialCredentialsError, + ProfileNotFound, +) from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig @@ -152,7 +157,12 @@ class BedrockMantleResponsesAPIConfig(OpenAIResponsesAPIConfig): stream=stream, fake_stream=fake_stream, ) - except BotoCoreError as e: + except ( + NoCredentialsError, + PartialCredentialsError, + ProfileNotFound, + CredentialRetrievalError, + ) as e: raise ValueError( "Bedrock Mantle auth failed: no Bearer token and no usable AWS " "credentials. Set BEDROCK_MANTLE_API_KEY (or AWS_BEARER_TOKEN_BEDROCK) " diff --git a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py index 7771049913a..92b5ca7b10b 100644 --- a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py +++ b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py @@ -12,7 +12,11 @@ import sys sys.path.insert(0, os.path.abspath("../../../../..")) import pytest -from botocore.exceptions import PartialCredentialsError, ProfileNotFound +from botocore.exceptions import ( + ConnectTimeoutError, + PartialCredentialsError, + ProfileNotFound, +) import litellm from litellm.llms.bedrock_mantle.responses.transformation import ( @@ -609,6 +613,37 @@ class TestBedrockMantleResponsesSigV4: assert "Bearer" in msg assert "SigV4" in msg or "IAM" in msg + def test_sts_transport_error_is_not_masked_as_credentials(self, monkeypatch): + # An AssumeRole / web-identity flow hits STS over the network, so a transient + # connection error must surface as itself, not be rewritten into the + # "no usable AWS credentials" message that would send the user to fix the + # wrong thing. + from unittest.mock import MagicMock + from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM + + monkeypatch.delenv("BEDROCK_MANTLE_API_KEY", raising=False) + monkeypatch.delenv("AWS_BEARER_TOKEN_BEDROCK", raising=False) + + signer = BaseAWSLLM() + signer.get_credentials = MagicMock( + side_effect=ConnectTimeoutError( + endpoint_url="https://sts.us-east-2.amazonaws.com" + ) + ) + cfg = BedrockMantleResponsesAPIConfig(aws_signer=signer) + + with pytest.raises(ConnectTimeoutError): + cfg.sign_request( + headers={}, + optional_params={ + "aws_role_name": "arn:aws:iam::000000000000:role/test-role", + "aws_region_name": "us-east-2", + }, + request_data={"input": "hi"}, + api_base="https://bedrock-mantle.us-east-2.api.aws/openai/v1/responses", + api_key=None, + ) + class TestBedrockMantleResponsesPricing: def test_gpt_5_5_pricing_and_mode(self, local_cost_map):