BerriAI/litellm · error · ValueError

file_id or file_data is required

Error message

file_id or file_data is required

What it means

Raised by HostedVLLM's _convert_file_to_video_url when a chat message content item of type 'file' has neither file_id nor file_data inside its file object. The transformation tries to convert file content into a video_url object; with an empty file dict there is nothing to put in the URL, so it fails fast with ValueError.

Source

Thrown at litellm/llms/hosted_vllm/chat/transformation.py:146

            mime_type = _parse_mime_type(file_data)
            if mime_type and mime_type.startswith("video/"):
                return True
        elif file_id:
            mime_type = _get_image_mime_type_from_url(file_id)
            if mime_type and mime_type.startswith("video/"):
                return True
        return False

    def _convert_file_to_video_url(self, content_item: ChatCompletionFileObject) -> ChatCompletionVideoObject:
        file: Final = content_item.get("file", {})
        file_id: Final = file.get("file_id")
        file_data: Final = file.get("file_data")

        if file_id:
            return ChatCompletionVideoObject(type="video_url", video_url=ChatCompletionVideoUrlObject(url=file_id))
        elif file_data:
            return ChatCompletionVideoObject(type="video_url", video_url=ChatCompletionVideoUrlObject(url=file_data))
        raise ValueError("file_id or file_data is required")

    @overload
    def _transform_messages(
        self, messages: list[AllMessageValues], model: str, is_async: Literal[True]
    ) -> Coroutine[Any, Any, list[AllMessageValues]]: ...

    @overload
    def _transform_messages(
        self,
        messages: list[AllMessageValues],
        model: str,
        is_async: Literal[False] = False,
    ) -> list[AllMessageValues]: ...

    def _transform_messages(
        self, messages: list[AllMessageValues], model: str, is_async: bool = False
    ) -> list[AllMessageValues] | Coroutine[Any, Any, list[AllMessageValues]]:
        """

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Populate one of the recognized keys: {'type':'file','file':{'file_id':'<url-or-id>'}} or {'type':'file','file':{'file_data':'data:video/mp4;base64,...'}}.
  2. If you intended an inline video, base64-encode it into a data URL and use file_data.
  3. If you intended a URL, put it in file_id (the code uses it directly as the video_url).
  4. Validate message content parts before calling litellm if they come from user input or another service.

Example fix

# before
messages=[{'role':'user','content':[
    {'type':'text','text':'describe this'},
    {'type':'file','file':{'path':'/tmp/clip.mp4'}},
]}]  # raises ValueError: file_id or file_data is required

# after
messages=[{'role':'user','content':[
    {'type':'text','text':'describe this'},
    {'type':'file','file':{'file_data':'data:video/mp4;base64,'+b64}},
]}]
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_file_part(part: dict) -> bool:
    if part.get("type") != "file":
        return True
    f = part.get("file") or {}
    return bool(f.get("file_id") or f.get("file_data"))

def validate_message_content(messages: list[dict]) -> None:
    for m in messages:
        content = m.get("content")
        if isinstance(content, list):
            for part in content:
                if not is_valid_file_part(part):
                    raise ValueError(f"file part missing file_id/file_data: {part}")

Type guard

def has_file_payload(part: dict) -> bool:
    """Narrows a chat content part to one HostedVLLM can convert to video_url."""
    f = part.get("file") or {}
    return isinstance(f, dict) and (isinstance(f.get("file_id"), str) or isinstance(f.get("file_data"), str))

Prevention

When it happens

Trigger: Sending a message content part like {'type':'file','file':{}} (or a file dict with only unrelated keys such as 'filename') to a hosted_vllm model. Only file_id or file_data are recognized; anything else falls through to the raise.

Common situations: Building multimodal messages generically and passing a file part with a local path or bytes under a non-standard key; migrating from OpenAI client code that used different file-object keys; upstream schema change where the producer stopped populating file_id/file_data.

Related errors


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