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.bodyarrived as JSON.req.fileremainedundefined.- 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.fileexists. - 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.