{"record":{"id":"f7f98f8dd0688ad0","repo":"BerriAI/litellm","slug":"empty-request-body-for-file-uploads-use-multipar","errorCode":null,"errorMessage":"Empty request body. For file uploads, use multipart/form-data content type with a file field. When using curl with --form/-F, do NOT set the Content-Type header manually.","messagePattern":"Empty request body\\. For file uploads, use multipart/form-data content type with a file field\\. When using curl with --form/-F, do NOT set the Content-Type header manually\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/ocr_endpoints/endpoints.py","lineNumber":148,"sourceCode":"\n    # --- JSON body (existing behavior) ---\n    try:\n        body = await request.body()\n    except RuntimeError:\n        # Body stream was consumed by auth middleware (e.g., form parsing).\n        body = b\"\"\n\n    if not body:\n        # The body may be empty because the auth middleware already parsed\n        # it as form data (e.g., _read_request_body called request.form()).\n        # Check if form data is available.\n        if getattr(request, \"_form\", None) is not None:\n            verbose_proxy_logger.debug(\n                \"OCR request body is empty but form data is available from middleware — processing as multipart form.\"\n            )\n            return await _parse_multipart_form(request)\n\n        raise ValueError(\n            \"Empty request body. For file uploads, use multipart/form-data content type \"\n            \"with a file field. When using curl with --form/-F, do NOT set the Content-Type \"\n            \"header manually.\"\n        )\n\n    try:\n        data: Final = orjson.loads(body)\n    except orjson.JSONDecodeError as e:\n        raise ValueError(\n            f\"Invalid JSON in request body: {e}. \"\n            \"Ensure the request body is valid JSON with Content-Type: application/json, \"\n            \"or use multipart/form-data for file uploads.\"\n        )\n\n    # Security: reject type=\"file\" documents received via JSON.\n    # The \"file\" document type is designed for local SDK usage where the\n    # caller and the process share a filesystem.  In the proxy context the\n    # caller is remote, so allowing a file-path string would let an","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/ocr_endpoints/endpoints.py#L130-L166","documentation":"Error \"Empty request body. For file uploads, use multipart/form-data content type with a file field. When using curl with --form/-F, do NOT set the Content-Type header manually.\" thrown in BerriAI/litellm.","triggerScenarios":"Thrown at litellm/proxy/ocr_endpoints/endpoints.py:148 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Send multipart/form-data with a file field (with curl --form/-F do not set Content-Type manually), or a valid JSON body."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}