BerriAI/litellm · error · BadRequestError

BedrockException - {error_str} . Enable 'litellm.modify_para

Error message

BedrockException - {error_str}
. Enable 'litellm.modify_params=True' (for PROXY do: `litellm_settings::modify_params: True`) to insert a dummy assistant message and fix this error.

What it means

Bedrock-specific: raised as BadRequestError when the error text contains 'Conversation blocks and tool result blocks cannot be provided in the same turn.' — i.e. your message list has a user turn containing both toolResult blocks and other conversation content, which the Bedrock Converse API forbids. The message tells you the fix: enable litellm.modify_params so LiteLLM inserts a dummy assistant message to satisfy Bedrock's schema.

Source

Thrown at litellm/litellm_core_utils/exception_mapping_utils.py:838

    exception_type: str,
    exception_provider: str,
    extra_information: str,
) -> None:
    if (
        "too many tokens" in error_str
        or "expected maxLength:" in error_str
        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),

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Set litellm.modify_params = True (or litellm_settings: modify_params: true in the proxy config) so LiteLLM inserts the required dummy assistant message.
  2. Or fix the history yourself: ensure every tool result sits in a user turn that follows an assistant turn containing the corresponding tool_use, with no extra content in the tool-result turn.
  3. Match every 'tool' role message to its preceding assistant tool_calls message.

Example fix

# before
import litellm
litellm.modify_params = False
resp = litellm.completion(model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0", messages=agent_history_with_tool_results)

# after
import litellm
litellm.modify_params = True
resp = litellm.completion(model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0", messages=agent_history_with_tool_results)
Defensive patterns

Strategy: validation

Validate before calling

def history_tool_blocks_are_separated(messages: list) -> bool:
    """Every tool ('tool' role / toolResult) message must directly follow an assistant message containing tool_calls."n    for i, m in enumerate(messages):
        if m.get("role") == "tool":
            if i == 0 or "tool_calls" not in (messages[i - 1] or {}):
                return False
            # no user content packed into the same turn as a tool result
        if m.get("role") == "user" and isinstance(m.get("content"), list):
            if any(b.get("type") == "tool_result" for b in m["content"]) and len(m["content"]) > 1:
                return False
    return True

Type guard

import litellm

def is_bedrock_tool_turn_error(e: BaseException) -> bool:
    return isinstance(e, litellm.BadRequestError) and "cannot be provided in the same turn" in str(e)

Try / catch

try:
    resp = litellm.completion(model="bedrock/...", messages=msgs)
except litellm.BadRequestError as e:
    if "cannot be provided in the same turn" in str(e):
        msgs = insert_dummy_assistant_after_tool_results(msgs)
        resp = litellm.completion(model="bedrock/...", messages=msgs)
    else:
        raise

Prevention

When it happens

Trigger: Sending an agentic transcript where a tool result is immediately followed by (or packed with) additional user content in the same turn — common after manual message-history manipulation or when the assistant tool_use turn is missing from history.

Common situations: Agent frameworks that append tool outputs plus a user message without an assistant turn in between; hand-built histories where the assistant's tool_use message was dropped; converting OpenAI-format tool messages to Bedrock converse format incorrectly.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f35684f225f67b94. Report an issue: GitHub.