BerriAI/litellm · error · ValueError

Failed to delete file

Error message

Failed to delete file: {raw_response.text}

What it means

Raised in GoogleAIStudioFilesHandler.transform_delete_file_response when the Gemini DELETE /v1beta/files/{name} call returns a non-success HTTP status. The success branch extracts the file id from the request URL and returns FileDeleted; on failure the raw response body (raw_response.text) is embedded verbatim in the ValueError, so the message contains Google's actual error payload (e.g. FILE_NOT_FOUND, PERMISSION_DENIED).

Solutions

  1. Read the embedded body text: if it contains 'File ... not found' (404), treat the delete as already-done and continue idempotently
  2. Confirm the id format matches the create response (files/<id>) and was created with the same API key/project
  3. For PERMISSION_DENIED/429 bodies, fix key scopes or throttle the deletion loop
  4. Guard concurrent deleters with a lock or single-owner cleanup job so the same file is not deleted twice

Example fix

# before
litellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)
# ValueError: Failed to delete file: {"error": {"code": 404, "message": "File not found..."}}

# after - treat not-found as success (idempotent delete)
try:
    litellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)
except ValueError as e:
    if 'not found' in str(e).lower() or '404' in str(e):
        pass  # already deleted / expired
    else:
        raise
Defensive patterns

Strategy: try-catch

Validate before calling

import re

def is_likely_gone(file_id: str, created_ts: float) -> bool:
    return time.time() - created_ts > 48 * 3600  # Gemini TTL ~48h → delete will 404

Try / catch

try:
    litellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)
except ValueError as e:
    body = str(e)
    if 'not found' in body.lower() or '"code": 404' in body:
        pass  # idempotent: already deleted/expired
    elif 'PERMISSION_DENIED' in body or '"code": 403' in body:
        raise PermissionError(body)
    else:
        raise

Prevention

When it happens

Trigger: Deleting a file that no longer exists (already deleted, or auto-expired after Gemini's ~48h TTL); a malformed or wrong-project file id (400); an API key lacking permission for that file (403); quota errors (429).

Common situations: Retry/idempotency logic calling delete twice; background cleanup jobs racing each other; file ids persisted long ago and expired; deleting a file created under a different Google Cloud project or API key.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/7c9785e55610e192. Report an issue: GitHub.

Appendix: source

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

        Google AI Studio returns an empty JSON object {} on successful deletion.
        """
        try:
            # Google AI Studio returns {} on successful deletion
            if raw_response.status_code == 200:
                # Extract file ID from the request URL if possible
                file_id = "deleted"
                if hasattr(raw_response, "request") and raw_response.request:
                    url: Final = str(raw_response.request.url)
                    if "/files/" in url:
                        file_id = url.split("/files/")[-1].split("?")[0]
                        # Add the files/ prefix if not present
                        if not file_id.startswith("files/"):
                            file_id = f"files/{file_id}"

                return FileDeleted(id=file_id, deleted=True, object="file")
            else:
                raise ValueError(f"Failed to delete file: {raw_response.text}")
        except Exception as e:
            verbose_logger.exception("Error parsing file delete response: %s", e)
            raise ValueError(f"Error parsing file delete response: {e}")

    def transform_list_files_request(
        self,
        purpose: str | None,
        optional_params: dict,
        litellm_params: dict,
    ) -> tuple[str, dict]:
        raise NotImplementedError("GoogleAIStudioFilesHandler does not support file listing")

    def transform_list_files_response(
        self,
        raw_response: httpx.Response,
        logging_obj: LiteLLMLoggingObj,
        litellm_params: dict,
    ) -> list[OpenAIFileObject]:

View on GitHub (pinned to 77b7c6c40c)