unslothai/unsloth · error · HTTPException
Empty upload payload
Error message
Empty upload payload
What it means
HTTP 400 from multipart upload when the streamed file copied to storage with zero bytes written (written == 0). The stored path is unlinked first, keeping the uploads dir clean. Equivalent of 815 for the browser-upload path: the part existed but carried no content.
Source
Thrown at studio/backend/hub/services/datasets/local.py:390
written = 0
upload_complete = False
try:
with open(stored_path, "wb") as f:
while chunk := await file.read(LOCAL_UPLOAD_CHUNK_BYTES):
written += len(chunk)
if written > max_bytes:
raise _upload_too_large(max_label)
await asyncio.to_thread(f.write, chunk)
upload_complete = True
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 = "Empty upload payload")
return UploadDatasetResponse(filename = filename, stored_path = str(stored_path))
def list_local_datasets_response() -> LocalDatasetsResponse:
return LocalDatasetsResponse(datasets = _build_local_dataset_items())
View on GitHub (pinned to 203007d190)
Solutions
- Check file.size > 0 on the client before allowing submit.
- If size looks right, verify the file is not a cloud-sync placeholder — open it locally first.
- Log the declared size (the server already early-rejects on `size` when available) to see whether client and disk disagree.
- Re-create the empty source file with real content and re-upload.
Example fix
// before
const fd = new FormData(); fd.append('file', file);
// after
if (!file || file.size === 0) return showError('Choose a non-empty file');
const fd = new FormData(); fd.append('file', file); Defensive patterns
Strategy: validation
Validate before calling
if (!file || file.size === 0) { showError('Choose a non-empty file'); return; }
const fd = new FormData(); fd.append('file', file); Type guard
function isNonEmptyFile(f: unknown): f is File {
return f instanceof File && f.size > 0;
} Try / catch
try {
await uploadDataset(fd);
} catch (e) {
if (e.status === 400 && /empty/i.test(e.body?.detail ?? '')) {
showEmptyFileError(file.name);
} else throw e;
} Prevention
- Gate the submit button on file.size > 0 (use the server's declared-size early check as backstop).
- Hydrate cloud-sync placeholders before selecting them.
- Reject 0-byte files in automated pipelines before they reach the API.
When it happens
Trigger: Submitting a 0-byte file part; a client constructing FormData with an empty Blob or empty File; some browsers reporting a File handle for a placeholder that streams zero bytes.
Common situations: User selects an in-progress download stub; JS creates `new File([], 'x.csv')` as a placeholder; sync-client placeholders again.
Related errors
- Dropped dataset is empty
- No dataset file was provided
- Empty file not allowed
- Dataset appears to be empty or could not be read
- Unsupported file type: {ext}. Allowed: {allowed}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/d29a442230d64f0f.
Report an issue: GitHub.