BerriAI/litellm · error · OCIError

Content type `{item_type}` is not supported by OCI

Error message

Content type `{item_type}` is not supported by OCI

What it means

The OCI GENERIC adapter only understands two content part types: 'text' and 'image_url'. Any other value of the 'type' field — e.g. 'audio_url', 'input_audio', 'video_url', 'file' — raises OCIError(400) "Content type `<value>` is not supported by OCI". It is a hard capability limit of the OCI GENERIC inference API surface as implemented here, enforced client-side.

Source

Thrown at litellm/llms/oci/chat/generic.py:81

        return OCIMessage(
            role=open_ai_to_generic_oci_role_map[role],
            content=[OCITextContentPart(text=content)],
            toolCalls=None,
            toolCallId=None,
        )

    for content_item in content:
        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):

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Strip or branch on content types not in {'text','image_url'} before routing a request to OCI.
  2. Route audio/video requests to a provider that supports them, keeping OCI for text+vision traffic.
  3. If you control the payload, transcribe audio upstream and send the transcript as a text part.

Example fix

# before
content=[{'type':'text','text':'summarize'}, {'type':'input_audio','input_audio':{'data':b64,'format':'wav'}}]

# after
content=[{'type':'text','text':'summarize'}, {'type':'image_url','image_url':{'url':img}}]  # audio handled by a dedicated STT step
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {'text', 'image_url'}
content = [p for p in content if p.get('type') in SUPPORTED]
assert all(p['type'] in SUPPORTED for p in content), 'unsupported content type for OCI'

Type guard

def is_oci_supported_part(part: object) -> bool:
    return isinstance(part, dict) and part.get('type') in ('text', 'image_url')

Try / catch

try:
    litellm.completion(model='oci/...', messages=msgs)
except OCIError as e:
    if 'not supported by OCI' in str(e):
        msgs = strip_unsupported_parts(msgs)  # drop audio/video/file parts
    raise

Prevention

When it happens

Trigger: Sending multimodal content valid for other providers (audio parts for OpenAI, video parts for Gemini) to an oci/ GENERIC model such as oci/meta.llama-3.2-90b-vision-instruct; reusing a provider-agnostic prompt builder that emits audio/file parts on every request.

Common situations: Porting an OpenAI or Gemini multimodal app to OCI without trimming unsupported modalities; a shared prompt template that conditionally includes an audio part depending on user input; newer OpenAI content types sneaking in via an SDK upgrade of the caller's framework.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/669d5065808be937. Report an issue: GitHub.