BerriAI/litellm · error · ValueError
Unsupported content type: {type(content_block)}
Error message
Unsupported content type: {type(content_block)} What it means
Raised while normalizing a user message's content for empty-text replacement (the function that swaps empty text blocks for a 'continue' message). It explicitly handles content being a str or a list of blocks; any other Python type — None, dict, int — hits the final ValueError.
Source
Thrown at litellm/litellm_core_utils/prompt_templates/factory.py:4130
modified_content_block: Final = content_block.copy()
for item in modified_content_block:
# Check if the list is empty
if item["type"] == "text":
if not item["text"].strip():
# Replace empty text with continue message
_user_continue_message = ChatCompletionUserMessage(
**(user_continue_message or DEFAULT_USER_CONTINUE_MESSAGE)
)
text = convert_content_list_to_str(_user_continue_message)
item["text"] = text
break
modified_message: Final = message.copy()
modified_message["content"] = modified_content_block
return modified_message
# Handle unsupported type
raise ValueError(f"Unsupported content type: {type(content_block)}")
def return_assistant_continue_message(
assistant_continue_message: str | ChatCompletionAssistantMessage | None = None,
) -> ChatCompletionAssistantMessage:
if assistant_continue_message and isinstance(assistant_continue_message, str):
return ChatCompletionAssistantMessage(
role="assistant",
content=assistant_continue_message,
)
elif assistant_continue_message and isinstance(assistant_continue_message, dict):
return ChatCompletionAssistantMessage(**assistant_continue_message)
else:
return DEFAULT_ASSISTANT_CONTINUE_MESSAGE
def _skip_empty_dict_blocks(blocks: list[dict]) -> list[dict]:
"""View on GitHub (pinned to 6c2dcb801b)
Solutions
- Set user message content to a non-empty string, or to a list of typed blocks.
- If content is None because of tool results, supply content: "" is not enough — use an explicit text block or omit the user message and use the tool role expected by the handler.
- Wrap single blocks in a list: content=[{"type":"text","text":"..."}].
Example fix
# before
{"role": "user", "content": None}
# after
{"role": "user", "content": [{"type": "text", "text": " "}]} Defensive patterns
Strategy: type-guard
Validate before calling
def sanitize_content(msg: dict) -> dict:
c = msg.get("content")
if c is None:
msg = {**msg, "content": [{"type": "text", "text": " "}]}
elif isinstance(c, dict):
msg = {**msg, "content": [c]}
return msg Type guard
def content_is_supported(c) -> bool:
return isinstance(c, (str, list)) Try / catch
try:
resp = litellm.completion(model="bedrock/...", messages=msgs)
except ValueError as e:
if "Unsupported content type" in str(e):
msgs = [sanitize_content(m) for m in msgs]
resp = litellm.completion(model="bedrock/...", messages=msgs) Prevention
- Never leave user-message content as None; always set a string or block list.
- Run a message-schema validator over outgoing payloads in CI.
When it happens
Trigger: A message whose 'content' key is None (common when a user message has tool results but content omitted), a single content-block dict instead of a list, or any non-str/non-list value, sent to a Bedrock Converse model.
Common situations: Messages built for OpenAI tool flows where content is optional; agent frameworks that emit content=None for tool-result turns; passing one content block as a bare dict {"type":"text",...} instead of wrapping it in a list.
Related errors
- BedrockException - {error_str} . Enable 'litellm.modify_para
- file_id and file_data are both None
- Unsupported image type. Expected either image url or base64
- Unable to convert openai tool calls={tool_calls} to bedrock
- model is required
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/701e2915258f91d9.
Report an issue: GitHub.