Image description

While building a simple video uploader in Next.js, I ran into an error that took way longer to fix than I expected:

{ message: 'Invalid image file', name: 'Error', http_code: 400 }

If you're uploading videos to Cloudinary using upload_stream and hit this error, this post will save you hours.

🔍 The Problem
I was sending a video/mp4 file using formData from my frontend and handling the upload inside a Next.js POST route using upload_stream from the cloudinary Node.js SDK.

Here’s a simplified version of the code:

ts
Copy
Edit
const result = await new Promise((resolve, reject) => {
  const uploadStream = cloudinary.v2.uploader.upload_stream(
    { folder: "Videos" },
    (error, result) => {
      if (error) reject(error)
      else resolve(result)
    }
  )
  uploadStream.end(buffer)
})

The file was valid, the form data was working, and the backend received everything correctly. But it kept throwing this error:

css
Copy
Edit
{ message: 'Invalid image file', name: 'Error', http_code: 400 }
At first, I thought something was wrong with the file type or encoding.

Nope. The problem was simpler...

💡 The Real Issue
Cloudinary defaults to resource_type: "image" unless you explicitly tell it otherwise.

So even if you send a video file, Cloudinary still tries to process it as an image... and obviously fails.

✅ The Fix
Just add this to your upload_stream options:

ts
Copy
Edit
{ folder: "Videos", resource_type: "video" }
Now the full code looks like this:
ts
Copy
Edit
const result = await new Promise((resolve, reject) => {
  const uploadStream = cloudinary.v2.uploader.upload_stream(
    { folder: "Videos", resource_type: "video" },
    (error, result) => {
      if (error) reject(error)
      else resolve(result)
    }
  )
  uploadStream.end(buffer)
})

And just like that, the upload works.

🧠 Lesson Learned
Cloudinary expects you to declare what kind of file you're uploading. If you don’t specify, it defaults to "image", which can lead to confusing errors when you're actually uploading a video or something else.

Use resource_type: "image" for images (default)

Use resource_type: "video" for video files

Use resource_type: "raw" for other binary files like PDFs, zips, etc.

🚀 Final Thoughts
These kinds of small but painful bugs are a great reminder: tools often have smart defaults, but they’re not always smart enough. Knowing how they assume things can save you time.

If you found this helpful, follow me on Dev.to — I share real bugs I solve while building with Next.js, Cloudinary, and other full-stack tools.

Happy building!