medusajs/medusa · error · MedusaError

No file was uploaded for importing

Error message

No file was uploaded for importing

What it means

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.

Source

Thrown at packages/medusa/src/api/admin/products/import/route.ts:19

import {
  AuthenticatedMedusaRequest,
  MedusaResponse,
} from "@medusajs/framework/http"
import { HttpTypes } from "@medusajs/framework/types"
import { MedusaError } from "@medusajs/framework/utils"
import { importProductsWorkflow } from "@medusajs/core-flows"

/**
 * @deprecated use `POST /admin/products/imports` instead.
 */
export const POST = async (
  req: AuthenticatedMedusaRequest<HttpTypes.AdminImportProductRequest>,
  res: MedusaResponse<HttpTypes.AdminImportProductResponse>
) => {
  const input = req.file as Express.Multer.File

  if (!input) {
    throw new MedusaError(
      MedusaError.Types.INVALID_DATA,
      "No file was uploaded for importing"
    )
  }

  const { result, transaction } = await importProductsWorkflow(req.scope).run({
    input: {
      filename: input.originalname,
      fileContent: input.buffer.toString("utf-8"),
    },
  })

  res
    .status(202)
    .json({ transaction_id: transaction.transactionId, summary: result })
}

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Send multipart/form-data with a 'file' field containing the CSV file
  2. Disable the submit button until a file is selected in the upload UI
  3. Inspect the actual request in devtools to confirm Content-Type is multipart and the part is named 'file'

Example fix

// before
await sdk.client.fetch("/admin/products/import", { method: "POST", body: JSON.stringify({}) })

// after
const form = new FormData()
form.append("file", new File([csvBlob], "products.csv", { type: "text/csv" }))
await fetch(`${baseUrl}/admin/products/import`, { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: form })
Defensive patterns

Strategy: validation

Validate before calling

if (!(file instanceof File) || file.size === 0) {
  throw new Error("Select a non-empty CSV file before importing")
}
const form = new FormData()
form.append("file", file)
await fetch(`${baseUrl}/admin/products/import`, { method: "POST", headers: auth, body: form })

Type guard

const isMultipartFile = (f: unknown): f is File =>
  f instanceof File && f.size > 0

Try / catch

try {
  await importProducts(form)
} catch (e: any) {
  if (e.statusCode === 400 && /no file/i.test(e.message)) showFilePickerError()
  else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/1086ebf0b1e3c56f. Report an issue: GitHub.