BerriAI/litellm · error · OCIError
Content item of type `text` must have a string `text` field
Error message
Content item of type `text` must have a string `text` field
What it means
A content part with type "text" must carry its payload in a string `text` field for OCI GENERIC. If `text` is missing, None, or a non-string (number, dict, list), translation aborts with OCIError 400. Fail-fast validation mirroring the OpenAI content-part contract OCI maps onto.
Solutions
- Ensure every {"type":"text"} part has a string: coerce with str(value) when building the message
- Default empty strings explicitly: text=msg.get("text") or "" if an empty text part is intentional
- Validate message shape with a type guard/serializer before calling litellm
- Check for None coming from optional chain construction (e.g. data.get("text") when key absent)
Example fix
# before
content = [{"type": "text", "text": 12345}]
# after
content = [{"type": "text", "text": "12345"}] Defensive patterns
Strategy: type-guard
Validate before calling
def coerce_text_parts(content: list) -> list:
return [
{**p, "text": str(p["text"])} if p.get("type") == "text" else p
for p in content
] Type guard
def is_valid_text_part(part) -> bool:
return part.get("type") == "text" and isinstance(part.get("text"), str) Prevention
- str()-coerce anything numeric inserted as text content at build time
- Treat text as a required field in your message dataclasses/pydantic models
When it happens
Trigger: messages=[{"role":"user","content":[{"type":"text"}]}] (missing text), [{"type":"text","text":123}] (int), or [{"type":"text","text":None}] against an oci/generic.* model. Raised locally in content adaptation before any HTTP request.
Common situations: Template code inserting numbers/None into text fields without str(); JSON where text serialized as a non-string; omitting the field when constructing parts programmatically; refactors renaming the field.
Related errors
- Content type ` ` is not supported by OCI
- Each content item must be a dictionary
- Each content item must have a string `type` field
- Each tool call must be a dictionary
- Message `content` must be a string or list of content parts
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9d57b85d762ad2da.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/oci/chat/generic.py:89
if not isinstance(content_item, dict):
raise OCIError(status_code=400, message="Each content item must be a dictionary")
item_type = content_item.get("type")
if not isinstance(item_type, str):
raise OCIError(
status_code=400,
message="Each content item must have a string `type` field",
)
if item_type not in ["text", "image_url"]:
raise OCIError(
status_code=400,
message=f"Content type `{item_type}` is not supported by OCI",
)
if item_type == "text":
text = content_item.get("text")
if not isinstance(text, str):
raise OCIError(
status_code=400,
message="Content item of type `text` must have a string `text` field",
)
new_content.append(OCITextContentPart(text=text))
elif item_type == "image_url":
image_url = content_item.get("image_url")
if isinstance(image_url, dict):
image_url = image_url.get("url")
if not isinstance(image_url, str):
raise OCIError(
status_code=400,
message="Prop `image_url` must be a string or an object with a `url` property",
)
new_content.append(OCIImageContentPart(imageUrl=OCIImageUrl(url=image_url)))
return OCIMessage(
role=open_ai_to_generic_oci_role_map[role],View on GitHub (pinned to 77b7c6c40c)