BerriAI/litellm · error · Exception
Prop `type` is not a string
Error message
Prop `type` is not a string
What it means
This module-level message-transform helper iterates each message's content items and reads content_item.get("type"). If type is missing, None, or otherwise falsy, it raises this bare Exception because it cannot look up a mapping for it. It assumes content is a list of typed parts following the OpenAI multimodal format ({type: "text"|"image_url", ...}).
Source
Thrown at litellm/llms/bytez/chat/transformation.py:393
}
def adapt_messages_to_bytez_standard(messages: list[dict]):
messages = _adapt_string_only_content_to_lists(messages)
new_messages: Final = []
for message in messages:
role = message["role"]
content: list = message["content"]
new_content = []
for content_item in content:
type: str | None = content_item.get("type")
if not type:
raise Exception("Prop `type` is not a string")
content_item_map = open_ai_to_bytez_content_item_map[type]
if not content_item_map:
raise Exception(f"Prop `{type}` is not supported")
new_type = content_item_map["type"]
value_name = content_item_map["value_name"]
value: str | None = content_item.get(value_name)
if not value:
raise Exception(f"Prop `{value_name}` is not a string")
new_content.append({"type": new_type, value_name: value})
new_messages.append({"role": role, "content": new_content})View on GitHub (pinned to 6c2dcb801b)
Solutions
- Ensure every content part is a dict with an explicit string 'type' ("text", "image_url", ...).
- Keep plain string content as a string (content="hello"), not ["hello"].
- Validate/normalize messages with a helper before calling litellm for Bytez.
Example fix
# before
messages = [{"role": "user", "content": ["describe this", {"url": "..."}]}]
# after
messages = [{"role": "user", "content": [
{"type": "text", "text": "describe this"},
{"type": "image_url", "image_url": {"url": "..."}},
]}] Defensive patterns
Strategy: type-guard
Validate before calling
def normalize_content(content):
"""Pass strings through; ensure every list part is a typed dict."""
if isinstance(content, str):
return [{"type": "text", "text": "content placeholder"}][0] # or return the string directly
normalized = []
for part in content:
if isinstance(part, str):
normalized.append({"type": "text", "text": part})
elif isinstance(part, dict) and not part.get("type"):
raise ValueError(f"content part missing 'type': {part!r}")
else:
normalized.append(part)
return normalized Type guard
from typing import Any
def is_typed_content_list(content: Any) -> bool:
"""True when content is a list of parts each carrying a non-empty string 'type'."""
if not isinstance(content, list) or not content:
return False
return all(
isinstance(p, dict) and isinstance(p.get("type"), str) and p["type"]
for p in content
) Try / catch
try:
litellm.completion(model="bytez/...", messages=messages)
except Exception as e:
if "Prop `type` is not a string" in str(e):
messages = [{"role": m["role"], "content": normalize_content(m["content"])} for m in messages]
litellm.completion(model="bytez/...", messages=messages)
else:
raise Prevention
- Always build multimodal parts with explicit 'type' keys; never put bare strings inside content lists.
- Run a message-normalization pass (validate/repair content parts) before provider calls.
- Add contract tests for message shapes when accepting user- or LLM-generated message payloads.
When it happens
Trigger: Sending a Bytez chat message whose content is a list of parts where a part lacks the 'type' key or has type: null/empty — e.g. hand-built multimodal content dicts, or content written as a plain string inside a list (["hello"]) instead of [{"type": "text", "text": "hello"}].
Common situations: Constructing vision/multimodal messages manually and forgetting the type field; wrapping plain strings in lists; upstream serialization stripping the field; models of content other than list (this helper assumes list) reaching the Bytez path.
Related errors
- kwarg `messages` must be an array of messages that follow th
- Prop `{type}` is not supported
- Prop `{value_name}` is not a string
- messages is required
- Invalid first message. Should always start with 'role'='user
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/8cecb80d89894194.
Report an issue: GitHub.