BerriAI/litellm · error · ValueError

Unsupported file content type: {type(file_content)}

Error message

Unsupported file content type: {type(file_content)}

What it means

extract_file_data accepts only a closed set of content types — file-like objects with .read(), bytes, and the earlier branches (PathLike, tuples, UploadFile). Anything else (int, dict, list, None after earlier handling, arbitrary objects) reaches the else branch and raises ValueError naming the offending type. This guards the file upload path against values that cannot be turned into bytes.

Source

Thrown at litellm/litellm_core_utils/prompt_templates/common_utils.py:818

            filename = Path(file_content).name
        with open(file_content, "rb") as f:
            content = f.read()
    elif isinstance(file_content, io.IOBase):
        # If it's a file-like object
        # Try to get filename from file handle if not already set
        if not filename and hasattr(file_content, "name"):
            filename = Path(file_content.name).name

        content = file_content.read()

        if isinstance(content, str):
            content = content.encode("utf-8")
        # Reset file pointer to beginning
        file_content.seek(0)
    elif isinstance(file_content, bytes):
        content = file_content
    else:
        raise ValueError(f"Unsupported file content type: {type(file_content)}")

    # Use provided content type or guess based on filename
    if not content_type:
        if filename:
            guessed_type: Final = mimetypes.guess_type(filename)[0]
            content_type = guessed_type if guessed_type else "application/octet-stream"
        else:
            content_type = "application/octet-stream"

    return ExtractedFileData(
        filename=filename,
        content=content,
        content_type=content_type,
        headers=file_headers,
    )


# ---------------------------------------------------------------------------

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Convert the value to bytes before passing: extract the actual content and pass bytes or a BytesIO handle.
  2. For framework objects, call their content accessor first (e.g. obj.content, obj.file.read()).
  3. If passing a file handle, ensure it is a real binary file object supporting read() and seek().
  4. Log type(file_data) at your call site to find where the wrong type enters.

Example fix

// before
file_data={'name':'a.pdf','body':'raw'}  # dict

# after
file_data=(('a.pdf'), b'%PDF-1.4 ...')  # (filename, bytes) tuple
Defensive patterns

Strategy: type-guard

Validate before calling

def is_supported_file_content(v) -> bool:
    return isinstance(v, (bytes, bytearray)) or (hasattr(v, 'read') and hasattr(v, 'seek'))

Type guard

from typing import Any, TypeGuard
from collections.abc import ByteString

def is_file_content(v: Any) -> TypeGuard[ByteString]:
    return isinstance(v, (bytes, bytearray, memoryview))

Try / catch

try:
    data = extract_file_data(file_data=content)
except ValueError as e:
    if 'Unsupported file content type' in str(e):
        content = content.read() if hasattr(content, 'read') else bytes(content)
        data = extract_file_data(file_data=content)
    else:
        raise

Prevention

When it happens

Trigger: Passing file_data as a dict (e.g. raw JSON payload), an int, or a generator; a file-like object without .read()/.seek(); None slipping through when earlier branches only partially matched; langchain/other-framework objects passed unconverted.

Common situations: Wrapping frameworks that hand over their own content abstractions; frontend JSON where file content arrives as a nested dict instead of bytes; partial refactors leaving placeholder values like 0 or {} in file blocks.

Related errors


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