BerriAI/litellm · error · BadRequestError

BedrockException

Error message

BedrockException - {error_str}

What it means

LiteLLM throws BadRequestError when Bedrock returns 'Malformed input request' - the request body does not match the target model's expected inference schema (bad message structure, unsupported field, invalid content block) and Bedrock refuses it before running inference. It is the generic 400 branch of the Bedrock mapper; the underlying error_str embedded in the message names the offending part. Same payload on a different Bedrock model can succeed because schemas differ per model family.

Solutions

  1. Read the error_str inside the message - Bedrock usually names the exact offending field
  2. Validate every message has non-empty content and a role the target model supports, and enable litellm drop_params=True to strip unsupported parameters
  3. Reproduce the raw call with boto3 bedrock-runtime.invoke_model to isolate whether your payload or litellm's transformation is at fault
  4. Verify the model id / inference profile string formatting (e.g. 'bedrock/us.anthropic.claude-3-5-sonnet-...:0')

Example fix

# before
resp = litellm.completion(model="bedrock/amazon.titan-text-express-v1", messages=messages, logit_bias={200: 2.0})

# after
import litellm
litellm.drop_params = True  # strip params the model rejects
messages = [m for m in messages if m.get("content")]  # drop empty-content blocks
resp = litellm.completion(model="bedrock/amazon.titan-text-express-v1", messages=messages)
Defensive patterns

Strategy: validation

Validate before calling

import litellm
litellm.drop_params = True

ALLOWED_ROLES = {'system', 'user', 'assistant', 'tool'}

def payload_is_sane(messages: list) -> bool:
    if not messages:
        return False
    return all(m.get('role') in ALLOWED_ROLES and m.get('content') for m in messages)

Type guard

import litellm

def is_malformed_request(e: BaseException) -> bool:
    return isinstance(e, litellm.BadRequestError) and 'Malformed input' in str(e)

Try / catch

try:
    resp = litellm.completion(model='bedrock/...', messages=messages)
except litellm.BadRequestError as e:
    log.error('bedrock rejected payload: %s', e)
    raise  # fix payload per the embedded error text; do not retry as-is

Prevention

When it happens

Trigger: litellm.completion(model='bedrock/...') with messages containing empty content, roles the model does not accept, model-unsupported parameters (logit_bias on Titan, top_k where unsupported), malformed image/system blocks, or a wrong inferenceProfileId embedded in the model string.

Common situations: Switching the bedrock/ model string without adapting the payload (Claude vs Titan vs Llama schemas differ); passing OpenAI-only fields through; empty-string content in a message after templating; Bedrock API drift after model version updates.

Related errors


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

Appendix: source

Thrown at litellm/litellm_core_utils/exception_mapping_utils.py:845

        or "Input is too long" in error_str
        or "prompt is too long" in error_str
        or "prompt: length: 1.." in error_str
        or "Too many input tokens" in error_str
    ):
        raise ContextWindowExceededError(
            message=f"BedrockException: Context Window Error - {error_str}",
            model=model,
            llm_provider="bedrock",
        )
    elif "Conversation blocks and tool result blocks cannot be provided in the same turn." in error_str:
        raise BadRequestError(
            message=f"BedrockException - {error_str}\n. Enable 'litellm.modify_params=True' (for PROXY do: `litellm_settings::modify_params: True`) to insert a dummy assistant message and fix this error.",
            model=model,
            llm_provider="bedrock",
            response=getattr(original_exception, "response", None),
        )
    elif "Malformed input request" in error_str:
        raise BadRequestError(
            message=f"BedrockException - {error_str}",
            model=model,
            llm_provider="bedrock",
            response=getattr(original_exception, "response", None),
        )
    elif "A conversation must start with a user message." in error_str:
        raise BadRequestError(
            message=f"BedrockException - {error_str}\n. Pass in default user message via `completion(..,user_continue_message=)` or enable `litellm.modify_params=True`.\nFor Proxy: do via `litellm_settings::modify_params: True` or user_continue_message under `litellm_params`",
            model=model,
            llm_provider="bedrock",
            response=getattr(original_exception, "response", None),
        )
    elif (
        "Unable to locate credentials" in error_str
        or "The security token included in the request is invalid" in error_str
    ):
        raise AuthenticationError(
            message=f"BedrockException Invalid Authentication - {error_str}",

View on GitHub (pinned to 77b7c6c40c)