{"record":{"id":"b5e4b24639b95802","repo":"unslothai/unsloth","slug":"empty-upload-payload-b5e4b2","errorCode":null,"errorMessage":"empty upload payload","messagePattern":"empty upload payload","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"studio/backend/routes/data_recipe/seed.py","lineNumber":671,"sourceCode":"    _LEGACY_UNSTRUCTURED_EXTS = {\".txt\", \".md\"}\n    if seed_source_type == \"unstructured\":\n        if ext not in _LEGACY_UNSTRUCTURED_EXTS:\n            allowed = \", \".join(sorted(_LEGACY_UNSTRUCTURED_EXTS))\n            raise HTTPException(\n                status_code = 400,\n                detail = f\"unsupported file type: {ext}. allowed: {allowed}\",\n            )\n    else:\n        if ext not in LOCAL_UPLOAD_EXTS:\n            allowed = \", \".join(sorted(LOCAL_UPLOAD_EXTS))\n            raise HTTPException(\n                status_code = 400,\n                detail = f\"unsupported file type: {ext}. allowed: {allowed}\",\n            )\n\n    file_bytes = _decode_base64_payload(payload.content_base64)\n    if not file_bytes:\n        raise HTTPException(status_code = 400, detail = \"empty upload payload\")\n    if len(file_bytes) > LOCAL_SEED_UPLOAD_MAX_BYTES:\n        raise HTTPException(\n            status_code = 413,\n            detail = f\"file too large (max {LOCAL_SEED_UPLOAD_MAX_LABEL})\",\n        )\n\n    ensure_dir(SEED_UPLOAD_DIR)\n    stored_name = f\"{uuid4().hex}_{filename}\"\n    stored_path = SEED_UPLOAD_DIR / stored_name\n    stored_path.write_bytes(file_bytes)\n\n    if seed_source_type == \"unstructured\":\n        preview_rows = _read_preview_rows_from_unstructured_file(\n            path = stored_path,\n            preview_size = int(payload.preview_size),\n            chunk_size = payload.unstructured_chunk_size,\n            chunk_overlap = payload.unstructured_chunk_overlap,\n        )","sourceCodeStart":653,"sourceCodeEnd":689,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/data_recipe/seed.py#L653-L689","documentation":"Raised after _decode_base64_payload returns falsy, meaning the content_base64 field decoded to zero bytes (or decoding yielded an empty result). The endpoint refuses to store an empty file, returning HTTP 400 with 'empty upload payload'. This is a client-side data problem, not a server fault.","triggerScenarios":"POST with content_base64 set to an empty string, base64 of b'' (i.e. '' or '=' padding artifacts), a base64 string that decodes to nothing, or the field omitted while the schema defaults it to empty. Occurs after the extension checks pass.","commonSituations":"Reading the file before it is fully written (0-byte read); base64-encoding an empty buffer because the file picker returned an empty File; a multipart-to-base64 conversion bug that drops the payload.","solutions":["Verify the source file exists and has non-zero size before encoding it.","Log the length of the base64 string client-side; anything under a few characters is a bug in the upload pipeline.","Check that the field name sent by the client matches the schema's content_base64 exactly (no truncation by a proxy or body parser)."],"exampleFix":"// before\nconst b64 = btoa(file.name); // encodes the NAME, not contents\n\n// after\nconst b64 = await fileToBase64(file); // reads File contents\nif (!b64 || b64.length < 4) throw new Error('file is empty');","handlingStrategy":"validation","validationCode":"const bytes = await file.arrayBuffer();\nif (bytes.byteLength === 0) throw new Error('selected file is empty');\nconst b64 = base64FromBytes(bytes);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check file.size > 0 in the picker before reading.","Unit-test the base64 conversion helper against empty inputs."],"tags":["validation","file-upload","base64"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}