{"record":{"id":"7c9785e55610e192","repo":"BerriAI/litellm","slug":"failed-to-delete-file-raw-response-text","errorCode":null,"errorMessage":"Failed to delete file: {raw_response.text}","messagePattern":"Failed to delete file: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/gemini/files/transformation.py","lineNumber":361,"sourceCode":"\n        Google AI Studio returns an empty JSON object {} on successful deletion.\n        \"\"\"\n        try:\n            # Google AI Studio returns {} on successful deletion\n            if raw_response.status_code == 200:\n                # Extract file ID from the request URL if possible\n                file_id = \"deleted\"\n                if hasattr(raw_response, \"request\") and raw_response.request:\n                    url: Final = str(raw_response.request.url)\n                    if \"/files/\" in url:\n                        file_id = url.split(\"/files/\")[-1].split(\"?\")[0]\n                        # Add the files/ prefix if not present\n                        if not file_id.startswith(\"files/\"):\n                            file_id = f\"files/{file_id}\"\n\n                return FileDeleted(id=file_id, deleted=True, object=\"file\")\n            else:\n                raise ValueError(f\"Failed to delete file: {raw_response.text}\")\n        except Exception as e:\n            verbose_logger.exception(\"Error parsing file delete response: %s\", e)\n            raise ValueError(f\"Error parsing file delete response: {e}\")\n\n    def transform_list_files_request(\n        self,\n        purpose: str | None,\n        optional_params: dict,\n        litellm_params: dict,\n    ) -> tuple[str, dict]:\n        raise NotImplementedError(\"GoogleAIStudioFilesHandler does not support file listing\")\n\n    def transform_list_files_response(\n        self,\n        raw_response: httpx.Response,\n        logging_obj: LiteLLMLoggingObj,\n        litellm_params: dict,\n    ) -> list[OpenAIFileObject]:","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/gemini/files/transformation.py#L343-L379","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\nlitellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)\n# ValueError: Failed to delete file: {\"error\": {\"code\": 404, \"message\": \"File not found...\"}}\n\n# after - treat not-found as success (idempotent delete)\ntry:\n    litellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)\nexcept ValueError as e:\n    if 'not found' in str(e).lower() or '404' in str(e):\n        pass  # already deleted / expired\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"import re\n\ndef is_likely_gone(file_id: str, created_ts: float) -> bool:\n    return time.time() - created_ts > 48 * 3600  # Gemini TTL ~48h → delete will 404","typeGuard":null,"tryCatchPattern":"try:\n    litellm.delete_file(file_id=fid, custom_llm_provider='gemini', api_key=KEY)\nexcept ValueError as e:\n    body = str(e)\n    if 'not found' in body.lower() or '\"code\": 404' in body:\n        pass  # idempotent: already deleted/expired\n    elif 'PERMISSION_DENIED' in body or '\"code\": 403' in body:\n        raise PermissionError(body)\n    else:\n        raise","preventionTips":["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"],"tags":["gemini","files-api","delete-file","http-error"],"backgroundTag":"resource-delete-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}