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
- Read the error_str inside the message - Bedrock usually names the exact offending field
- Validate every message has non-empty content and a role the target model supports, and enable litellm drop_params=True to strip unsupported parameters
- Reproduce the raw call with boto3 bedrock-runtime.invoke_model to isolate whether your payload or litellm's transformation is at fault
- 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
- Lint messages (non-empty content, valid roles) before sending
- Enable drop_params=True when switching between Bedrock model families
- Reproduce new payload shapes with boto3 invoke_model before wiring into litellm
- Pin model ids and payload shapes together - change both or neither
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
- Error converting to valid response block=
- Error processing response
- AgentCore: Failed to read/parse JSON response body
- Amazon Nova Canvas INPAINTING requires either maskPrompt or…
- Amazon Nova Canvas requires a text prompt. Pass a non-empty…
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)