Uploading an image with Node.js and multer working with postman but not from frontend

Summary

This incident involved a file upload pipeline using Node.js, Express, and multer that worked flawlessly in Postman but consistently failed when triggered from a React frontend. The backend received text fields correctly, but req.file was always undefined, causing the upload logic to break.

Root Cause

The root cause was that the frontend was not sending a multipart/form-data request, even though Postman was. Axios defaults to JSON unless explicitly overridden.

Because of this:

  • Multer never saw a file stream, so it skipped file parsing.
  • req.body arrived as JSON.
  • req.file remained undefined.
  • The controller attempted to read req.file.path, causing a server error.

Why This Happens in Real Systems

This failure mode is extremely common because:

  • Browsers do not automatically convert objects into multipart/form-data.
  • Axios does not infer multipart uploads from nested objects.
  • Developers often pass { image: fileObject } instead of a FormData instance.
  • Middleware ordering (auth → multer → controller) hides the real issue until runtime.

Real-World Impact

When this occurs in production:

  • Uploads silently fail while text fields still work.
  • Server crashes if code assumes req.file exists.
  • Data integrity issues arise because DB entries are created without images.
  • Debugging becomes confusing because Postman works but the browser does not.

Example or Code (if necessary and relevant)

Below is the correct frontend code required to make multer receive the file:

const formData = new FormData();
formData.append("categoryName", categoryData.categoryName);
formData.append("description", categoryData.description);
formData.append("nested", categoryData.nested);
formData.append("image", categoryData.image); // MUST be a File object

await axios.post("/categories", formData, {
  headers: { "Content-Type": "multipart/form-data" }
});

This ensures the request matches what Postman sends.

How Senior Engineers Fix It

Experienced engineers typically:

  • Inspect the actual network request in DevTools to confirm the content type.
  • Ensure the frontend uses FormData, not JSON.
  • Validate that the file input is a File or Blob, not an empty object.
  • Confirm multer is placed after auth middleware but before the controller.
  • Add defensive checks such as:
    • if (!req.file) return res.status(400).json({ error: "Image required" });

Why Juniors Miss It

Junior developers often overlook this because:

  • They assume Axios automatically handles file uploads.
  • They don’t realize that Postman and browsers behave differently.
  • They trust console logs showing { image: {} } without understanding that this is not a real file object.
  • They focus on backend debugging even though the issue originates in the frontend.
  • They are unfamiliar with how multipart/form-data encoding works.

This issue is a classic example of how frontend request formatting can completely break backend middleware, even when the backend is correct.

Leave a Comment