{"record":{"id":"27c71be6278e6411","repo":"unslothai/unsloth","slug":"failed-to-delete-uploaded-files","errorCode":null,"errorMessage":"failed to delete uploaded files","messagePattern":"failed to delete uploaded files","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"studio/backend/routes/data_recipe/seed.py","lineNumber":616,"sourceCode":"\n    block_dir = (UNSTRUCTURED_UPLOAD_ROOT / block_id).resolve()\n    if not block_dir.is_relative_to(UNSTRUCTURED_UPLOAD_ROOT.resolve()):\n        raise HTTPException(400, \"Invalid block_id: outside upload root\")\n    if not block_dir.exists():\n        return {\"status\": \"ok\", \"deleted\": False}\n\n    try:\n        shutil.rmtree(block_dir)\n    except OSError as exc:\n        raise log_and_http_error(\n            exc,\n            500,\n            \"failed to delete uploaded files\",\n            event = \"data_recipe.seed.unstructured_block_delete_failed\",\n            log = logger,\n        ) from exc\n    if block_dir.exists():\n        raise HTTPException(500, \"failed to delete uploaded files\")\n    return {\"status\": \"ok\", \"deleted\": True}\n\n\n@router.post(\"/seed/inspect-upload\", response_model = SeedInspectResponse)\ndef inspect_seed_upload(payload: SeedInspectUploadRequest) -> SeedInspectResponse:\n    if payload.file_ids is not None:\n        if len(payload.file_ids) == 0:\n            raise HTTPException(400, \"file_ids must not be empty\")\n        _validate_safe_id(payload.block_id, \"block_id\")\n        for fid in payload.file_ids:\n            _validate_safe_id(fid, \"file_id\")\n        preview_rows = _read_preview_rows_from_multi_files(\n            block_id = payload.block_id,\n            file_ids = payload.file_ids,\n            file_names = payload.file_names,\n            preview_size = payload.preview_size,\n            chunk_size = payload.unstructured_chunk_size,\n            chunk_overlap = payload.unstructured_chunk_overlap,","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/data_recipe/seed.py#L598-L634","documentation":"HTTP 500 raised by DELETE /seed/unstructured-block/{block_id} when shutil.rmtree raises OSError, or when the rmtree call returned but block_dir still exists (partial delete). It is logged via log_and_http_error with event data_recipe.seed.unstructured_block_delete_failed.","triggerScenarios":"Block delete when files are locked/open (Windows), permission bits deny removal, another process concurrently recreates files in the directory, or an NFS/container volume races the delete.","commonSituations":"Concurrent uploads to the same block during delete; read-only mounts; files held open by an extraction subprocess; container volume with slow eventual consistency.","solutions":["Retry the delete after the concurrent upload/preview finishes — the most common cause is a race with an in-flight write.","Check directory permissions/ownership of the uploads root for the backend process user.","If it persists, list surviving files in the block dir to identify which file cannot be removed and why (lsof/permissions)."],"exampleFix":"# before\nawait api.deleteBlock(blockId)  # one-shot, throws on race\n\n# after\nfor attempt in range(3):\n    try:\n        await api.deleteBlock(blockId); break\n    except HttpError as e:\n        if e.status != 500 or attempt == 2: raise\n        await asyncio.sleep(1)  # let concurrent upload finish","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"Catch the 500 'failed to delete uploaded files', wait briefly (concurrent write race is the usual cause), and retry the block delete up to 2–3 times with backoff; escalate to manual filesystem inspection if it persists.","preventionTips":["Block new uploads to a block before deleting it (disable the UI).","Check permissions on the uploads root for the backend user in container images.","Avoid running cleanup jobs that rmtree the same directories concurrently."],"tags":["filesystem","delete","http-500","race-condition"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}