I noticed an issue with the images on my blog, a while ago. The images were broken in production, but not in development. I am using the next/image component, which is a great component for optimizing images. Here's what I saw below.
It felt weird because this is the same image component I've been using for a while now and there's been no issue. So the first thing I did was to check my current version of Next.js. I was on v13.5.6
, which isn't bad. I checked the latest version of Next.js on their npm page and found out that 14.0.0 is available.
I updated my Next.js version to v14.0.0
and deployed again. The images were still broken and I found a new error in the build log on Netlify.
unhandledRejection ReferenceError
: Headers is not defined
I wasn't a bit surprised. At first, I thought to myself, "Next.js people have started again". But the issue was due to my negligence. I failed to update the dependency management in the site configuration.
Turned out that next@14.0.0
requires a newer version of nodejs to manage HTTP Headers and many other things I don't know about. Doing this still did not fix the broken image issue.
But the error, ReferenceError: Headers is not defined
was gone.
Serverless/Edge function timeout
After a few hours of debugging and reading about the issues of other devs on the Netlify forums and GitHub. I found out that the issue was due to a serverless/edge function timeout.
The next/image component was trying to fetch the images from the serverless function, but the function timed out. This caused the images to be broken.
The serverless function on Netlify responsible for next images uses a tool called ipx
under the hood. But, it keeps failing to fetch the image resources, returning an error with a 502
status code. So why exactly does it keep failing?
I found out that the default timeout for serverless functions on Netlify is 10 seconds. And the images on my blog are fairly large even after I've compressed them. I think the average size of the images on my blog is about 400KB, and I have several articles.
This means that the serverless function is trying to fetch a lot of images that Next.js has optimized to be compatible with various browsers. And it's taking more than 10 seconds to fetch all the images. So the serverless function times out and returns a 502
status code.
How to fix it
Although this is a temporary solution, it fixes the broken images in production. But, that meant I had to trade off the default image optimization that Next.js provides. I had to disable the image optimization by setting the unoptimized
property to true
in the image component, like so:
Now, I've lost access to the various formats and srcsets (with sizes that scale according to a Device Pixel Ratio) that the optimization process provides. Formerly, if you inspect the source, this is what the image tag looks like:
But now, I serve the images in the default format, which is png
, and the srcset
is gone. This is what the image tag looks like now:
If you have a lot of images, and you want to follow the unoptimized
approach, it is easier to update this preference in your next.config.js
file like so:
What's next?
The funny thing about this error is that Vercel supports this out of the box. I had to try and deploy this site on Vercel to see if the issue was from Next.js or Netlify. And it worked perfectly on Vercel. I didn't have to do anything. I just deployed and the images were fixed.
I'll try to see if I can find a workaround for increasing the timeout for serverless functions on Netlify. I doubt I'll find anything because I have to be on a Pro plan to do such. I'll still try though.
But for now, I'll stick with the temporary solution, since my site's DNS is already pointing to Netlify. If I don't find any solution, I'll have to move to Vercel. I'll update this post if I find a solution.