unslothai/unsloth · error · HTTPException

Dropped dataset is empty

Error message

Dropped dataset is empty

What it means

HTTP 400 from native upload when the source file copied successfully but zero bytes were written (written == 0). The stored file is unlinked immediately so no empty dataset clutters the uploads dir. It specifically means the lease's file existed and was readable but had no content.

Source

Thrown at studio/backend/hub/services/datasets/local.py:350

            while chunk := source.read(LOCAL_UPLOAD_CHUNK_BYTES):
                written += len(chunk)
                if written > max_bytes:
                    raise _upload_too_large(max_label)
                target.write(chunk)
        upload_complete = True
    except OSError as exc:
        raise HTTPException(
            status_code = 400,
            detail = "Dropped dataset could not be read.",
        ) from exc
    finally:
        if not upload_complete:
            with suppress(OSError):
                stored_path.unlink(missing_ok = True)

    if written == 0:
        stored_path.unlink(missing_ok = True)
        raise HTTPException(status_code = 400, detail = "Dropped dataset is empty")

    return UploadDatasetResponse(filename = filename, stored_path = str(stored_path))


async def upload_dataset_response(
    file: UploadFile | None, native_path_lease: str | None = None
) -> UploadDatasetResponse:
    if native_path_lease:
        return await asyncio.to_thread(
            _native_upload_dataset_response,
            native_path_lease,
        )
    if file is None:
        raise HTTPException(status_code = 400, detail = "No dataset file was provided")

    filename, stored_path, max_bytes, max_label = _upload_destination(
        file.filename or "dataset_upload"
    )

View on GitHub (pinned to 203007d190)

Solutions

  1. Check the file size in the OS before importing — anything 0 bytes will be rejected.
  2. For cloud-sync placeholders, open the file locally first to force hydration, then re-import.
  3. Re-download or regenerate the source file if it was a truncated transfer.
  4. Add a client-side non-empty check after file selection.

Example fix

// before
importLease(file)  // 0-byte file passes
// after
if (file.size === 0) { showError('File is empty'); return; }
importLease(file);
Defensive patterns

Strategy: validation

Validate before calling

import os

def non_empty_file(path: str | os.PathLike) -> bool:
    return os.path.getsize(path) > 0

Try / catch

try:
    upload_dataset(client, native_path_lease=lease)
except HTTPStatusError as e:
    if e.response.status_code == 400 and "is empty" in e.response.text:
        alert_user_file_empty(path)  # hydrate sync placeholders, then re-pick
    else:
        raise

Prevention

When it happens

Trigger: Importing a 0-byte file (interrupted download, placeholder created by a sync client, `touch`ed file); a sparse file that reads as empty.

Common situations: Cloud-sync placeholder files (OneDrive/Dropbox) not yet hydrated to real content; downloads that failed silently leaving a 0-byte stub; user creates an empty .csv intending to fill it later.

Related errors


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