BerriAI/litellm · error · BadRequestError

BedrockException - {error_str} . Pass in default user messag

Error message

BedrockException - {error_str}
. Pass in default user message via `completion(..,user_continue_message=)` or enable `litellm.modify_params=True`.
For Proxy: do via `litellm_settings::modify_params: True` or user_continue_message under `litellm_params`

What it means

Bedrock-specific: BadRequestError raised when the error text contains 'A conversation must start with a user message.' — your first non-system message was not a user message (typically an assistant message first). The error message offers two fixes: pass user_continue_message to completion() or enable litellm.modify_params so LiteLLM prepends a default user message.

Source

Thrown at litellm/litellm_core_utils/exception_mapping_utils.py:852

            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}",
            model=model,
            llm_provider="bedrock",
            response=getattr(original_exception, "response", None),
        )
    elif "AccessDeniedException" in error_str:
        raise PermissionDeniedError(
            message=f"BedrockException PermissionDeniedError - {error_str}",

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass user_continue_message: litellm.completion(..., user_continue_message={"role": "user", "content": "..."}).
  2. Or set litellm.modify_params = True (proxy: litellm_settings.modify_params: true) to auto-insert a default user message.
  3. Or fix the history: ensure messages[0] after the optional system message has role 'user'.

Example fix

# before
resp = litellm.completion(model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0", messages=[{"role": "assistant", "content": "Sure, here is..."}])

# after
resp = litellm.completion(
    model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0",
    messages=[{"role": "assistant", "content": "Sure, here is..."}],
    user_continue_message={"role": "user", "content": "continue"},
)
Defensive patterns

Strategy: validation

Validate before calling

def starts_with_user_message(messages: list) -> bool:
    non_system = [m for m in messages if m.get("role") != "system"]
    return bool(non_system) and non_system[0].get("role") == "user"

Type guard

import litellm

def is_bedrock_first_turn_error(e: BaseException) -> bool:
    return isinstance(e, litellm.BadRequestError) and "must start with a user message" in str(e)

Try / catch

try:
    resp = litellm.completion(model="bedrock/...", messages=msgs)
except litellm.BadRequestError as e:
    if "must start with a user message" in str(e):
        msgs = [{"role": "user", "content": "continue"}, *msgs]
        resp = litellm.completion(model="bedrock/...", messages=msgs)
    else:
        raise

Prevention

When it happens

Trigger: Sending a transcript that starts with an assistant turn — e.g. prefilled assistant responses, resuming a conversation from a saved history whose first user turn was dropped, or trimming that removed the leading user message.

Common situations: Prefill-style prompting (assistant-first), agent loops that persist and reload history with the opening user turn stripped, or log-replay tools replaying partial transcripts.

Related errors


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