{"record":{"id":"c1158d9d632bd003","repo":"unslothai/unsloth","slug":"uploaded-file-is-empty","errorCode":null,"errorMessage":"Uploaded file is empty.","messagePattern":"Uploaded file is empty\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/rag.py","lineNumber":146,"sourceCode":"                block = source.read(1 << 20)\n                if not block:\n                    break\n                size += len(block)\n                if cap and size > cap:\n                    break\n                out.write(block)\n    except OSError:\n        _remove_stored_upload(stored_path)\n        raise\n    if cap and size > cap:\n        _remove_stored_upload(stored_path)\n        raise HTTPException(\n            status_code = 413,\n            detail = f\"File exceeds the {cap // (1024 * 1024)} MB upload limit.\",\n        )\n    if size == 0:\n        _remove_stored_upload(stored_path)\n        raise HTTPException(status_code = 400, detail = empty_detail)\n    return stored_path, filename\n\n\ndef _save_upload(file: UploadFile) -> tuple[str, str]:\n    \"\"\"Persist a browser upload; returns (stored_path, filename).\"\"\"\n    filename = _sanitize_filename(file.filename or \"document\")\n    return _persist_upload_stream(\n        file.file,\n        filename,\n        empty_detail = \"Uploaded file is empty.\",\n    )\n\n\ndef _save_native_path_upload(lease: str) -> tuple[str, str]:\n    \"\"\"Persist a desktop drop; returns (stored_path, filename).\n\n    The webview never gets to name a path directly: Rust signs the path it saw and we\n    re-verify + re-stat that grant here before reading a byte.","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/rag.py#L128-L164","documentation":"After streaming a browser upload, _persist_upload_stream() finds size == 0: the file transferred but contained no bytes. The just-created empty stored file is removed and HTTP 400 is returned with empty_detail, which _save_upload sets to 'Uploaded file is empty.'.","triggerScenarios":"Submitting a multipart upload whose file part has zero bytes — a placeholder/empty file created by another tool, a truncated file, or a form submission where the file input references an already-deleted file.","commonSituations":"User selects a 0-byte file left by a failed export or sync client; automated scripts post an empty file handle; tests using fixture files that were never populated.","solutions":["Check the source file on disk is non-empty (ls -l) and re-create/re-export it if it is zero bytes.","Validate file.size > 0 client-side before enabling the upload button.","In scripts, assert os.path.getsize(path) > 0 before attaching."],"exampleFix":"// before\nformData.append('file', fileInput.files[0]); // 0-byte file -> 400\n// after\nif (fileInput.files[0].size === 0) { showError('File is empty'); return; }\nformData.append('file', fileInput.files[0]);","handlingStrategy":"validation","validationCode":"if (file.size === 0) { notify('File is empty'); return; } // before any fetch","typeGuard":"const isNonEmptyFile = (f: File): boolean => f.size > 0;","tryCatchPattern":null,"preventionTips":["Disable submit while the selected file is 0 bytes.","Treat zero-byte files in sync folders as corrupt exports and re-create them before upload.","In test fixtures, assert size > 0 so empty files never reach the API."],"tags":["http-400","file-upload","empty-file","rag","studio-backend"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}