BerriAI/litellm · error · BedrockError

{str(e)}

Error message

{str(e)}

What it means

Final catch-all in the async streaming maker: any exception other than httpx.HTTPStatusError and httpx.TimeoutException — connection errors, DNS failures, SSL problems, unexpected payload types — is re-raised as BedrockError 500 with str(e) as the message. The 500 is synthetic: it was generated by LiteLLM's wrapper, not reported by AWS.

Source

Thrown at litellm/llms/bedrock/chat/invoke_handler.py:235

            decoder = AWSEventStreamDecoder(model=model, json_mode=json_mode)
            completion_stream = decoder.aiter_bytes(response.aiter_bytes(chunk_size=stream_chunk_size))

        # LOGGING
        logging_obj.post_call(
            input=messages,
            api_key="",
            original_response="first stream response received",
            additional_args={"complete_input_dict": data},
        )

        return completion_stream
    except httpx.HTTPStatusError as err:
        error_code: Final = err.response.status_code
        raise BedrockError(status_code=error_code, message=err.response.text)
    except httpx.TimeoutException:
        raise BedrockError(status_code=408, message="Timeout error occurred.")
    except Exception as e:
        raise BedrockError(status_code=500, message=str(e))


def make_sync_call(
    client: HTTPHandler | None,
    api_base: str,
    headers: dict,
    data: str,
    signed_json_body: bytes | None,
    model: str,
    messages: list,
    logging_obj: Logging,
    fake_stream: bool = False,
    json_mode: bool | None = False,
    bedrock_invoke_provider: litellm.BEDROCK_INVOKE_PROVIDERS_LITERAL | None = None,
    stream_chunk_size: int | None = None,
):
    try:
        if client is None:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Enable verbose logging and read the embedded str(e) — it names the real underlying exception
  2. Verify basic connectivity from the same environment: curl https://bedrock.<region>.amazonaws.com
  3. Fix DNS, proxy, or CA-certificate issues revealed by the message rather than retrying blindly
  4. For genuinely transient causes, retry on status 500 with capped attempts
Defensive patterns

Strategy: try-catch

Validate before calling

import socket

# cheap pre-flight: can we resolve and reach the bedrock endpoint?
region = "us-west-2"
try:
    socket.create_connection((f"bedrock.{region}.amazonaws.com", 443), timeout=5)
except OSError as e:
    raise RuntimeError(f"No network path to Bedrock in {region}: {e}")

resp = await litellm.acompletion(model="bedrock/...", messages=msgs, stream=True)

Try / catch

try:
    stream = await litellm.acompletion(model="bedrock/...", messages=msgs, stream=True)
except BedrockError as e:
    if e.status_code == 500:
        logger.error("Wrapped client failure (500 is synthetic): %s", e.message)  # e.message holds str(orig)
        if is_transient_network_error(e.message):
            await asyncio.sleep(2)
            stream = await litellm.acompletion(model="bedrock/...", messages=msgs, stream=True)
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: httpx.ConnectError or DNS resolution failure reaching bedrock.<region>.amazonaws.com; TLS certificate verification errors from missing CA bundles; protocol errors during stream setup; bugs in upstream parsing surfacing as generic exceptions.

Common situations: Containers or CI without egress routes/DNS to AWS; custom CA environments where cert verification fails; network policy changes mid-deployment; air-gapped clusters suddenly asked to call Bedrock.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/48c5a9eb45ed9d18. Report an issue: GitHub.