{"record":{"id":"314055a01c90dbb1","repo":"unslothai/unsloth","slug":"no-file-was-provided","errorCode":null,"errorMessage":"No file was provided.","messagePattern":"No file was provided\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/rag.py","lineNumber":197,"sourceCode":"    filename = _sanitize_filename(grant.canonical_path.name)\n    try:\n        with open(grant.canonical_path, \"rb\") as source:\n            return _persist_upload_stream(\n                source,\n                filename,\n                empty_detail = \"Dropped file is empty.\",\n            )\n    except OSError as exc:\n        raise HTTPException(status_code = 400, detail = \"Dropped file could not be read.\") from exc\n\n\ndef _resolve_document_upload(\n    file: UploadFile | None, native_path_lease: str | None\n) -> tuple[str, str]:\n    if native_path_lease:\n        return _save_native_path_upload(native_path_lease)\n    if file is None:\n        raise HTTPException(status_code = 400, detail = \"No file was provided.\")\n    return _save_upload(file)\n\n\ndef _remove_stored_upload(stored_path: str | None) -> None:\n    \"\"\"Best-effort cleanup for files saved by _save_upload.\"\"\"\n    if not stored_path:\n        return\n    try:\n        uploads = os.path.realpath(str(rag_uploads_root()))\n        target = os.path.realpath(stored_path)\n        if os.path.isfile(target) and os.path.commonpath([uploads, target]) == uploads:\n            os.remove(target)\n    except Exception:  # noqa: BLE001 - DB/index deletion has already succeeded.\n        logger.warning(\"failed to remove RAG upload %s\", stored_path, exc_info = True)\n\n\ndef _is_managed_preview_path(stored_path: str) -> bool:\n    uploads = os.path.realpath(str(rag_uploads_root()))","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/rag.py#L179-L215","documentation":"_resolve_document_upload() dispatches between the two upload channels: if native_path_lease is set it attaches by native path, otherwise it requires a multipart file part. When both are absent — no file part and no lease — it raises HTTP 400 'No file was provided.' before anything is persisted.","triggerScenarios":"POSTing the document-upload endpoint with neither the 'file' multipart part nor the 'nativePathLease' form field — e.g. an empty form submit, a request built without attaching either field, or a client that names the fields differently.","commonSituations":"Frontend form allows submit with no file selected; field-name mismatch (client sends 'native_path_lease' while the backend expects alias 'nativePathLease'); curl/script that forgets -F file=@...; automated tests posting empty bodies.","solutions":["Attach a file part or a valid nativePathLease form field (exact alias spelling) to the request.","Make the file input required client-side so the request cannot fire empty.","In scripts, double-check curl -F field names against the endpoint signature."],"exampleFix":"# before\ncurl -X POST .../documents -F ocr=true  # 400 No file was provided\n# after\ncurl -X POST .../documents -F file=@doc.pdf -F ocr=true","handlingStrategy":"validation","validationCode":"if (!file && !nativePathLease) { throw new Error('attach a file or provide nativePathLease'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the exact field names: multipart 'file' or form field 'nativePathLease' (camelCase alias).","Require at least one input in the form before enabling submit.","Integration-test the endpoint with a bare POST to catch field-name regressions early."],"tags":["http-400","file-upload","request-validation","rag","studio-backend"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}