{"record":{"id":"9d57b85d762ad2da","repo":"BerriAI/litellm","slug":"content-item-of-type-text-must-have-a-string-te","errorCode":null,"errorMessage":"Content item of type `text` must have a string `text` field","messagePattern":"Content item of type `text` must have a string `text` field","errorType":"validation","errorClass":"OCIError","httpStatus":400,"severity":"error","filePath":"litellm/llms/oci/chat/generic.py","lineNumber":89,"sourceCode":"        if not isinstance(content_item, dict):\n            raise OCIError(status_code=400, message=\"Each content item must be a dictionary\")\n\n        item_type = content_item.get(\"type\")\n        if not isinstance(item_type, str):\n            raise OCIError(\n                status_code=400,\n                message=\"Each content item must have a string `type` field\",\n            )\n        if item_type not in [\"text\", \"image_url\"]:\n            raise OCIError(\n                status_code=400,\n                message=f\"Content type `{item_type}` is not supported by OCI\",\n            )\n\n        if item_type == \"text\":\n            text = content_item.get(\"text\")\n            if not isinstance(text, str):\n                raise OCIError(\n                    status_code=400,\n                    message=\"Content item of type `text` must have a string `text` field\",\n                )\n            new_content.append(OCITextContentPart(text=text))\n\n        elif item_type == \"image_url\":\n            image_url = content_item.get(\"image_url\")\n            if isinstance(image_url, dict):\n                image_url = image_url.get(\"url\")\n            if not isinstance(image_url, str):\n                raise OCIError(\n                    status_code=400,\n                    message=\"Prop `image_url` must be a string or an object with a `url` property\",\n                )\n            new_content.append(OCIImageContentPart(imageUrl=OCIImageUrl(url=image_url)))\n\n    return OCIMessage(\n        role=open_ai_to_generic_oci_role_map[role],","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/chat/generic.py#L71-L107","documentation":"For content parts with type 'text', the OCI GENERIC adapter requires the 'text' field to be a string. A text part whose 'text' is missing, None, a number, or a list raises OCIError(400) \"Content item of type `text` must have a string `text` field\" before the request is sent.","triggerScenarios":"Sending {'type':'text','text':None} or {'type':'text','text':123} to an oci/ GENERIC model; building parts from template variables where a value can be None; f-string parts accidentally wrapped in a list.","commonSituations":"Optional prompt fields defaulting to None and still emitted as parts; data from JSON where text is sometimes numeric; a refactor changing text from str to a richer object.","solutions":["Coerce text values to str and skip empty parts: if v is not None: parts.append({'type':'text','text':str(v)}).","Add a pre-flight assertion that every type=='text' part has isinstance(part['text'], str).","Fix the upstream data source so prompt text is always a plain string."],"exampleFix":"# before\n{'type':'text','text': None}\n\n# after\n# build only when a value exists\nparts = [{'type':'text','text': str(v)} for v in values if v is not None]","handlingStrategy":"type-guard","validationCode":"content = [\n    {'type': 'text', 'text': str(p['text'])}\n    for p in content\n    if p.get('type') == 'text' and p.get('text') is not None\n]","typeGuard":"def is_valid_text_part(part: object) -> bool:\n    return (\n        isinstance(part, dict)\n        and part.get('type') == 'text'\n        and isinstance(part.get('text'), str)\n    )","tryCatchPattern":null,"preventionTips":["Coerce prompt variables with str() and skip None values when assembling parts.","Add CI tests that every generated text part passes a type guard."],"tags":["oci","input-validation","content-parts","type-mismatch"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}