next.js icon indicating copy to clipboard operation
next.js copied to clipboard

[Regression] AVIF fails to render with The requested resource isn't a valid image for ... received null

Open joshunger opened this issue 2 months ago • 7 comments

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/brave-goodall-pnz3tm

To Reproduce

  1. Open https://codesandbox.io/p/devbox/brave-goodall-pnz3tm
  2. View Preview and notice broken image.
  3. View terminal and notice output:
 ⨯ The requested resource isn't a valid image for /_next/static/media/atgiftcard.81b93929.avif received null

Current vs. Expected behavior

I expect the image to render.

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 15.6.0-canary.27 // Latest available version is detected (15.6.0-canary.27).
  eslint-config-next: N/A
  react: 19.1.1
  react-dom: 19.1.1
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Image (next/image)

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

I'll do some additional debugging.

joshunger avatar Sep 24 '25 16:09 joshunger

It looks like the detected image format is heif which is returning null. It would be super helpful if we could include this format in the error message in the future?

I ran the image through https://squoosh.app/ to fix the issue which now correctly renders and falls into the buffer detection

if ([0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66].every((b, i) => !b || buffer[i] === b)) {
    return AVIF;
}

This impacted several of our avif images.

joshunger avatar Sep 24 '25 16:09 joshunger

After bumping my version from 15.3.4 to 15.5.4 i am getting the same error for 90% of my images (pngs/jpgs) in the public folder:

⨯ The requested resource isn't a valid image for xxx.png received null

Not sure what's causing it, I re-downgraded to 15.3.4 in the mean time and everything is back to normal.

On 15.5.4 if i disable the image optimization pipeline in the config then the pictures show up correctly.

mt-bt avatar Sep 24 '25 19:09 mt-bt

@mt-bt maybe attach a few images that reproduce your issue? I modified node_modules/next/dist/server/image-optimizer.js and added some console.logs in detectContentType to get the detected type.

I think there are a couple of serious regressions around image handling possibly... we are also seeing images being returned unsized and unoptimized. I'll do some additional investigation. Ah, I think we had sharp installed from 14 which causes installation errors now we're on 15.

joshunger avatar Sep 25 '25 14:09 joshunger

The same mistake. SVGs are rendered normally, but PNGs give an error.

next.js 16.0.1, page router

UPD: It works fine in version 15.5.6

wolfcreative avatar Oct 30 '25 11:10 wolfcreative

Next JS 16.0.7 next/image still has this issue

AVIF animated images

Downgraded to 15.3.4, works fine.

pat1379 avatar Dec 03 '25 22:12 pat1379

We have the same issue, JPG images stopped working after upgrade.

I traced that the regression was introduced in Next.js version 15.4.5. The last working version is 15.4.4. Note however that this version has a serious security vulnerability so you should downgrade to version 15.3.6 instead if choosing to do so.

When bisecting the issue, you must delete .next folder between tests. If you run on a working version and switch to a broken version, it still works unless you delete .next, probably due to cached images.

We have assetPrefix: '/ecommerce' in our next.config.js and removing it makes the images work. Our image is located at public/ecommerce/hero-image.jpg, so I'm suspecting the original config may have been incorrect and this might actually be a bug fix that now fails with previously working (but incorrect) config.

plaa avatar Dec 09 '25 13:12 plaa

We actually need to use assetPrefix: '/ecommerce' since our Frontdoor only routes paths starting with /ecommerce to our app, thus the default /_next/image will not be routed to our app. We have a custom image loader that adds the /ecommerce prefix so images are fetched from /ecommerce/_next/image:

  if (src.startsWith('/ecommerce/')) {
    const searchParams = new URLSearchParams(`w=${width}&q=${quality || 75}`);
    return `/ecommerce/_next/image?url=${encodeURIComponent(src)}&${searchParams.toString()}`;
  }

My guess is that after this change, the image optimizer is adding assetPrefix to the path it's loading from, or something similar. Thus when the query param contains url=/ecommerce/_next/static/media/hero-image.dac4aed4.jpg it's actually doubling the /ecommerce prefix.

As a workaround we now strip the /ecommerce prefix in the custom image loader:

  if (src.startsWith('/ecommerce')) {
    // Strip /ecommerce prefix due to bug in Next image loader
    const strippedSrc = src.replace(/^\/ecommerce/, '');
    const searchParams = new URLSearchParams(`w=${width}&q=${quality || 75}`);
    return `/ecommerce/_next/image?url=${encodeURIComponent(strippedSrc)}&${searchParams.toString()}`;
  }

This is very hacky and brittle to break on future Next.js upgrades, so we're also writing an E2E test to verify images work as expected. The images worked correctly in Storybook, so even visual snapshot tests didn't notice anything wrong before we deployed to QA.

plaa avatar Dec 10 '25 08:12 plaa

Good to know: AVIF is just a HEIF variant that uses AV1 as its video codec.

https://github.com/bigcat88/pillow_heif/issues/8

tats-u avatar Dec 13 '25 04:12 tats-u