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
- Read the embedded body text: if it contains 'File ... not found' (404), treat the delete as already-done and continue idempotently
- Confirm the id format matches the create response (files/<id>) and was created with the same API key/project
- For PERMISSION_DENIED/429 bodies, fix key scopes or throttle the deletion loop
- 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
- Treat delete as idempotent: absorb 404/not-found bodies
- Skip deleting files older than the ~48h TTL — they are already gone
- Persist file ids with creation timestamps so cleanup jobs can pre-filter
- Serialize concurrent deleters so the same file is not deleted twice
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
- Error parsing file delete response
- Error parsing file retrieve response
- Error parsing file upload response
- GoogleAIStudioFilesHandler does not support file content…
- GoogleAIStudioFilesHandler does not support file listing
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)