BerriAI/litellm · error · ValueError

File data is required

Error message

File data is required

What it means

transform_create_file_request() takes the OpenAI-style create_file_data dict and extracts create_file_data['file']. If the key is absent (value None) it raises 'File data is required' — the two-step resumable upload protocol needs the raw bytes and filename from the file entry before it can compute content length and start the upload.

Source

Thrown at litellm/llms/gemini/files/transformation.py:120

        return optional_params

    def transform_create_file_request(
        self,
        model: str,
        create_file_data: CreateFileRequest,
        optional_params: dict,
        litellm_params: dict,
    ) -> dict:
        """
        Transform the OpenAI-style file creation request into Gemini's format

        Returns:
            dict: Contains both request data and headers for the two-step upload
        """
        # Extract the file information
        file_data: Final = create_file_data.get("file")
        if file_data is None:
            raise ValueError("File data is required")

        # Use the common utility function to extract file data
        extracted_data: Final = extract_file_data(file_data)

        # Get file size
        file_size: Final = len(extracted_data["content"])

        # Step 1: Initial resumable upload request
        headers: Final = {
            "X-Goog-Upload-Protocol": "resumable",
            "X-Goog-Upload-Command": "start",
            "X-Goog-Upload-Header-Content-Length": str(file_size),
            "X-Goog-Upload-Header-Content-Type": extracted_data["content_type"],
            "Content-Type": "application/json",
        }
        headers.update(extracted_data["headers"])  # Add any custom headers

        # Initial metadata request body

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass the file argument: litellm.create_file(model='gemini/', file=open('data.pdf','rb'), purpose='user_data').
  2. When building the payload programmatically, assert 'file' is present and non-None before invoking create_file.
  3. Open the file in binary mode and keep the handle alive until the call returns.

Example fix

# before
litellm.create_file(model="gemini/", purpose="user_data")  # no file -> ValueError

# after
with open("report.pdf", "rb") as f:
    litellm.create_file(model="gemini/", file=f, purpose="user_data")
Defensive patterns

Strategy: validation

Validate before calling

def validate_create_file_args(file) -> None:
    if file is None:
        raise ValueError("create_file requires an open binary file object")
    if not hasattr(file, "read"):
        raise TypeError("file must be a file-like object, not a path string")

Type guard

def is_file_like(obj: object) -> bool:
    return hasattr(obj, "read") and hasattr(obj, "close")

Try / catch

try:
    litellm.create_file(model="gemini/", file=f, purpose="user_data")
except ValueError as e:
    if "File data is required" in str(e):
        raise RuntimeError("Open the file and pass it via file=...") from e
    raise

Prevention

When it happens

Trigger: Calling the file-creation transformation with a payload dict lacking the 'file' key, e.g. {'filename': 'a.png'} or an accidentally empty dict — typically when calling litellm.create_file without the file argument or with it under a different name.

Common situations: Migrating from OpenAI's files API where the parameter shape differs; passing a path string instead of a file object; kwargs built dynamically where the 'file' entry was never added because the upstream file handle was None.

Related errors


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