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
- Convert the value to bytes before passing: extract the actual content and pass bytes or a BytesIO handle.
- For framework objects, call their content accessor first (e.g. obj.content, obj.file.read()).
- If passing a file handle, ensure it is a real binary file object supporting read() and seek().
- 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
- Normalize file inputs to bytes or file handles at your API boundary.
- Add schema validation (e.g. pydantic) on inbound file blocks so bad types fail early with clear errors.
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
- extract_file_data does not accept bare str inputs. Pass byte
- file_id and file_data are both None
- LLM Router not initialized. Ensure models added to proxy.
- Unified id does not contain {marker!r}: {file_id[:80]!r}
- LiteLLM Managed File object with id={file_id} has no file_ob
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/141a6e758fb32089.
Report an issue: GitHub.