unslothai/unsloth · error · HTTPException

failed to delete uploaded files

Error message

failed to delete uploaded files

What it means

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.

Source

Thrown at studio/backend/routes/data_recipe/seed.py:616

    block_dir = (UNSTRUCTURED_UPLOAD_ROOT / block_id).resolve()
    if not block_dir.is_relative_to(UNSTRUCTURED_UPLOAD_ROOT.resolve()):
        raise HTTPException(400, "Invalid block_id: outside upload root")
    if not block_dir.exists():
        return {"status": "ok", "deleted": False}

    try:
        shutil.rmtree(block_dir)
    except OSError as exc:
        raise log_and_http_error(
            exc,
            500,
            "failed to delete uploaded files",
            event = "data_recipe.seed.unstructured_block_delete_failed",
            log = logger,
        ) from exc
    if block_dir.exists():
        raise HTTPException(500, "failed to delete uploaded files")
    return {"status": "ok", "deleted": True}


@router.post("/seed/inspect-upload", response_model = SeedInspectResponse)
def inspect_seed_upload(payload: SeedInspectUploadRequest) -> SeedInspectResponse:
    if payload.file_ids is not None:
        if len(payload.file_ids) == 0:
            raise HTTPException(400, "file_ids must not be empty")
        _validate_safe_id(payload.block_id, "block_id")
        for fid in payload.file_ids:
            _validate_safe_id(fid, "file_id")
        preview_rows = _read_preview_rows_from_multi_files(
            block_id = payload.block_id,
            file_ids = payload.file_ids,
            file_names = payload.file_names,
            preview_size = payload.preview_size,
            chunk_size = payload.unstructured_chunk_size,
            chunk_overlap = payload.unstructured_chunk_overlap,

View on GitHub (pinned to 203007d190)

Solutions

  1. Retry the delete after the concurrent upload/preview finishes — the most common cause is a race with an in-flight write.
  2. Check directory permissions/ownership of the uploads root for the backend process user.
  3. If it persists, list surviving files in the block dir to identify which file cannot be removed and why (lsof/permissions).

Example fix

# before
await api.deleteBlock(blockId)  # one-shot, throws on race

# after
for attempt in range(3):
    try:
        await api.deleteBlock(blockId); break
    except HttpError as e:
        if e.status != 500 or attempt == 2: raise
        await asyncio.sleep(1)  # let concurrent upload finish
Defensive patterns

Strategy: retry

Try / catch

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.

Prevention

When it happens

Trigger: 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.

Common situations: Concurrent uploads to the same block during delete; read-only mounts; files held open by an extraction subprocess; container volume with slow eventual consistency.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/27c71be6278e6411. Report an issue: GitHub.