{"record":{"id":"1086ebf0b1e3c56f","repo":"medusajs/medusa","slug":"no-file-was-uploaded-for-importing","errorCode":null,"errorMessage":"No file was uploaded for importing","messagePattern":"No file was uploaded for importing","errorType":"exception","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/medusa/src/api/admin/products/import/route.ts","lineNumber":19,"sourceCode":"import {\n  AuthenticatedMedusaRequest,\n  MedusaResponse,\n} from \"@medusajs/framework/http\"\nimport { HttpTypes } from \"@medusajs/framework/types\"\nimport { MedusaError } from \"@medusajs/framework/utils\"\nimport { importProductsWorkflow } from \"@medusajs/core-flows\"\n\n/**\n * @deprecated use `POST /admin/products/imports` instead.\n */\nexport const POST = async (\n  req: AuthenticatedMedusaRequest<HttpTypes.AdminImportProductRequest>,\n  res: MedusaResponse<HttpTypes.AdminImportProductResponse>\n) => {\n  const input = req.file as Express.Multer.File\n\n  if (!input) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      \"No file was uploaded for importing\"\n    )\n  }\n\n  const { result, transaction } = await importProductsWorkflow(req.scope).run({\n    input: {\n      filename: input.originalname,\n      fileContent: input.buffer.toString(\"utf-8\"),\n    },\n  })\n\n  res\n    .status(202)\n    .json({ transaction_id: transaction.transactionId, summary: result })\n}\n","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/medusa/src/api/admin/products/import/route.ts#L1-L36","documentation":"Thrown by POST /admin/products/import when req.file is unset, i.e. the multipart request carried no actual file part. The route casts req.file to a Multer file and requires it before running importProductsWorkflow.","triggerScenarios":"Sending the request without multipart/form-data, with the file under the wrong field name (must be 'file'), or with an empty/omitted file part.","commonSituations":"SDK/fetch clients sending JSON instead of FormData, upload forms where the user did not select a file, proxies stripping multipart bodies, or wrong field naming in custom upload code.","solutions":["Send multipart/form-data with a 'file' field containing the CSV file","Disable the submit button until a file is selected in the upload UI","Inspect the actual request in devtools to confirm Content-Type is multipart and the part is named 'file'"],"exampleFix":"// before\nawait sdk.client.fetch(\"/admin/products/import\", { method: \"POST\", body: JSON.stringify({}) })\n\n// after\nconst form = new FormData()\nform.append(\"file\", new File([csvBlob], \"products.csv\", { type: \"text/csv\" }))\nawait fetch(`${baseUrl}/admin/products/import`, { method: \"POST\", headers: { Authorization: `Bearer ${token}` }, body: form })","handlingStrategy":"validation","validationCode":"if (!(file instanceof File) || file.size === 0) {\n  throw new Error(\"Select a non-empty CSV file before importing\")\n}\nconst form = new FormData()\nform.append(\"file\", file)\nawait fetch(`${baseUrl}/admin/products/import`, { method: \"POST\", headers: auth, body: form })","typeGuard":"const isMultipartFile = (f: unknown): f is File =>\n  f instanceof File && f.size > 0","tryCatchPattern":"try {\n  await importProducts(form)\n} catch (e: any) {\n  if (e.statusCode === 400 && /no file/i.test(e.message)) showFilePickerError()\n  else throw e\n}","preventionTips":["Always send multipart/form-data with part named 'file'","Disable submit until a file is chosen","Log the request Content-Type in failing upload code"],"tags":["admin","products","import","multipart","file-upload"],"backgroundTag":"missing-file-upload","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}