{"record":{"id":"970da06530411ef0","repo":"BerriAI/litellm","slug":"prop-image-url-must-be-a-string-or-an-object-wit","errorCode":null,"errorMessage":"Prop `image_url` must be a string or an object with a `url` property","messagePattern":"Prop `image_url` must be a string or an object with a `url` property","errorType":"validation","errorClass":"OCIError","httpStatus":400,"severity":"error","filePath":"litellm/llms/oci/chat/generic.py","lineNumber":100,"sourceCode":"                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],\n        content=new_content,\n        toolCalls=None,\n        toolCallId=None,\n    )\n\n\ndef adapt_messages_to_generic_oci_standard_tool_call(role: str, tool_calls: list) -> OCIMessage:\n    \"\"\"Convert an assistant tool-call message to OCI format.\"\"\"\n    tool_calls_formatted: Final = []\n    for tool_call in tool_calls:\n        if not isinstance(tool_call, dict):","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/chat/generic.py#L82-L118","documentation":"For image_url content parts, the adapter accepts either a plain string ('image_url': 'https://...') or an OpenAI-style object ('image_url': {'url': '...'}). If after unwrapping the value is not a string, OCIError(400) \"Prop `image_url` must be a string or an object with a `url` property\" is raised. Notably, an object whose 'url' key is missing or None also fails, because the unwrapped value is not a str.","triggerScenarios":"Sending {'type':'image_url','image_url':{'data':b64bytes}} (data instead of url), 'image_url': None, or an object where 'url' is missing/None to an oci/ GENERIC model. Also {'image_url': {'url': None}}.","commonSituations":"Confusing base64 data-field conventions across providers; dicts built from optional values where the url never got populated; passing an httpx.URL or pathlib.Path object instead of a string.","solutions":["Use the OpenAI shape: {'type':'image_url','image_url':{'url':'https://...'}} or the shorthand string form.","Ensure the url key exists and is a non-empty string; str() any URL-like objects before building the part.","For base64 images, use a data URL string ('data:image/png;base64,....') as the url value."],"exampleFix":"# before\n{'type':'image_url','image_url':{'data': b64_bytes}}\n\n# after\n{'type':'image_url','image_url':{'url': f'data:image/png;base64,{b64_str}'}}","handlingStrategy":"type-guard","validationCode":"def to_image_part(url_or_obj) -> dict:\n    url = url_or_obj.get('url') if isinstance(url_or_obj, dict) else url_or_obj\n    assert isinstance(url, str) and url, 'image_url must be a string or {\"url\": str}'\n    return {'type': 'image_url', 'image_url': {'url': url}}","typeGuard":"def is_valid_image_part(part: object) -> bool:\n    if not (isinstance(part, dict) and part.get('type') == 'image_url'):\n        return False\n    iu = part.get('image_url')\n    url = iu.get('url') if isinstance(iu, dict) else iu\n    return isinstance(url, str) and bool(url)","tryCatchPattern":null,"preventionTips":["Standardize on the OpenAI nested form {'image_url': {'url': ...}} across your codebase.","For base64 images always emit a data: URL string, never raw bytes or a 'data' key."],"tags":["oci","input-validation","vision","content-parts"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}