{"record":{"id":"a7b4d3ca2122f31e","repo":"unslothai/unsloth","slug":"dropped-dataset-is-empty","errorCode":null,"errorMessage":"Dropped dataset is empty","messagePattern":"Dropped dataset is empty","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"studio/backend/hub/services/datasets/local.py","lineNumber":350,"sourceCode":"            while chunk := source.read(LOCAL_UPLOAD_CHUNK_BYTES):\n                written += len(chunk)\n                if written > max_bytes:\n                    raise _upload_too_large(max_label)\n                target.write(chunk)\n        upload_complete = True\n    except OSError as exc:\n        raise HTTPException(\n            status_code = 400,\n            detail = \"Dropped dataset could not be read.\",\n        ) from exc\n    finally:\n        if not upload_complete:\n            with suppress(OSError):\n                stored_path.unlink(missing_ok = True)\n\n    if written == 0:\n        stored_path.unlink(missing_ok = True)\n        raise HTTPException(status_code = 400, detail = \"Dropped dataset is empty\")\n\n    return UploadDatasetResponse(filename = filename, stored_path = str(stored_path))\n\n\nasync def upload_dataset_response(\n    file: UploadFile | None, native_path_lease: str | None = None\n) -> UploadDatasetResponse:\n    if native_path_lease:\n        return await asyncio.to_thread(\n            _native_upload_dataset_response,\n            native_path_lease,\n        )\n    if file is None:\n        raise HTTPException(status_code = 400, detail = \"No dataset file was provided\")\n\n    filename, stored_path, max_bytes, max_label = _upload_destination(\n        file.filename or \"dataset_upload\"\n    )","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/hub/services/datasets/local.py#L332-L368","documentation":"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.","triggerScenarios":"Importing a 0-byte file (interrupted download, placeholder created by a sync client, `touch`ed file); a sparse file that reads as empty.","commonSituations":"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.","solutions":["Check the file size in the OS before importing — anything 0 bytes will be rejected.","For cloud-sync placeholders, open the file locally first to force hydration, then re-import.","Re-download or regenerate the source file if it was a truncated transfer.","Add a client-side non-empty check after file selection."],"exampleFix":"// before\nimportLease(file)  // 0-byte file passes\n// after\nif (file.size === 0) { showError('File is empty'); return; }\nimportLease(file);","handlingStrategy":"validation","validationCode":"import os\n\ndef non_empty_file(path: str | os.PathLike) -> bool:\n    return os.path.getsize(path) > 0","typeGuard":null,"tryCatchPattern":"try:\n    upload_dataset(client, native_path_lease=lease)\nexcept HTTPStatusError as e:\n    if e.response.status_code == 400 and \"is empty\" in e.response.text:\n        alert_user_file_empty(path)  # hydrate sync placeholders, then re-pick\n    else:\n        raise","preventionTips":["Force-hydrate cloud-sync placeholder files (open them locally) before importing.","Check size > 0 right after file selection and block the import button otherwise.","Treat 0-byte downloads as corrupt and re-download the source."],"tags":["upload","native-import","empty-file","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}