Error context (from production / Netlify logs)
- Message:
[ERROR] [Error: The requested resource isn't a valid image.] { statusCode: 400 }
- Fingerprint:
grafana-fn-error-the-requested-resource-isn-t-a-valid-image-statuscode-n
- Hit count: 10 (first seen 2026-06-30 09:00:03 UTC)
- Stack / URL: none captured (
function_name: null, request_id: 01KWCGEYEE8RGWNEZ4YSBVRJ3R)
Root-cause analysis
This error is thrown by Next.js's built-in image optimizer (/_next/image, in next/dist/server/image-optimizer.js) when it fetches a remote image URL that does not return decodable image bytes — e.g. the upstream host responds with an HTML error/404 page, a redirect to a login page, an expired/deleted asset, or an unexpected Content-Type. Next.js then rejects the response with statusCode: 400 and the message above.
The site optimizes images from ~25 remote hosts (next.config.js → images.remotePatterns, lines ~131-160). The highest-risk sources are third-party assets that routinely expire or get deleted upstream, which the site has no control over:
- Event images:
img.evbuc.com (Eventbrite), images.lumacdn.com (Luma), secure.meetupstatic.com (Meetup)
- Avatars / user content:
avatars*.githubusercontent.com, unavatar.io, pbs.twimg.com, i.imgur.com
- Token / data images:
coin-images.coingecko.com, s3-dcl1.ethquokkaops.io
When any such URL 404s or returns non-image content, the optimizer throws this 400. Because no URL is attached to the log line, the exact offending source can't be pinpointed from this alert alone; the low, steady hit count (10 over ~2 weeks) is consistent with a handful of stale external assets rather than a code regression.
Why this is not a trivial fix
There is no missing redirect / typo / null-check to change. Mitigation is architectural and spans multiple image entry points (src/components/Image/CardImage.tsx, src/components/Image/MarkdownImage.tsx, src/components/ui/avatar.tsx, plus event/community list rendering). Options, roughly in order of preference:
- Client-side
onError fallback on the next/image usages that render external URLs, swapping to a placeholder when the optimizer 400s (the avatar component already does this pattern — extend it to card/event images).
unoptimized (or a passthrough loader) for the volatile third-party hosts (events, coingecko, unavatar) so a bad upstream response is served/skipped without invoking the optimizer, instead of surfacing a 400 from the function.
- Add URL logging / a custom loader so future occurrences capture the offending source and can be triaged precisely.
Suggested approach
Start with (3) to get visibility (attach the failing src to the log), then apply (1)/(2) to the event and avatar surfaces where third-party image rot is most likely. This should be validated against the events and community pages.
Affected files
next.config.js (images.remotePatterns)
src/components/Image/CardImage.tsx
src/components/Image/MarkdownImage.tsx
src/components/ui/avatar.tsx
Filed by the automated recovery agent from a captured production error. Confidence: low (root cause identified; fix is architectural/multi-file).
Error context (from production / Netlify logs)
[ERROR] [Error: The requested resource isn't a valid image.] { statusCode: 400 }grafana-fn-error-the-requested-resource-isn-t-a-valid-image-statuscode-nfunction_name: null,request_id: 01KWCGEYEE8RGWNEZ4YSBVRJ3R)Root-cause analysis
This error is thrown by Next.js's built-in image optimizer (
/_next/image, innext/dist/server/image-optimizer.js) when it fetches a remote image URL that does not return decodable image bytes — e.g. the upstream host responds with an HTML error/404 page, a redirect to a login page, an expired/deleted asset, or an unexpectedContent-Type. Next.js then rejects the response withstatusCode: 400and the message above.The site optimizes images from ~25 remote hosts (
next.config.js→images.remotePatterns, lines ~131-160). The highest-risk sources are third-party assets that routinely expire or get deleted upstream, which the site has no control over:img.evbuc.com(Eventbrite),images.lumacdn.com(Luma),secure.meetupstatic.com(Meetup)avatars*.githubusercontent.com,unavatar.io,pbs.twimg.com,i.imgur.comcoin-images.coingecko.com,s3-dcl1.ethquokkaops.ioWhen any such URL 404s or returns non-image content, the optimizer throws this 400. Because no URL is attached to the log line, the exact offending source can't be pinpointed from this alert alone; the low, steady hit count (10 over ~2 weeks) is consistent with a handful of stale external assets rather than a code regression.
Why this is not a trivial fix
There is no missing redirect / typo / null-check to change. Mitigation is architectural and spans multiple image entry points (
src/components/Image/CardImage.tsx,src/components/Image/MarkdownImage.tsx,src/components/ui/avatar.tsx, plus event/community list rendering). Options, roughly in order of preference:onErrorfallback on thenext/imageusages that render external URLs, swapping to a placeholder when the optimizer 400s (the avatar component already does this pattern — extend it to card/event images).unoptimized(or a passthrough loader) for the volatile third-party hosts (events, coingecko, unavatar) so a bad upstream response is served/skipped without invoking the optimizer, instead of surfacing a 400 from the function.Suggested approach
Start with (3) to get visibility (attach the failing
srcto the log), then apply (1)/(2) to the event and avatar surfaces where third-party image rot is most likely. This should be validated against the events and community pages.Affected files
next.config.js(images.remotePatterns)src/components/Image/CardImage.tsxsrc/components/Image/MarkdownImage.tsxsrc/components/ui/avatar.tsxFiled by the automated recovery agent from a captured production error. Confidence: low (root cause identified; fix is architectural/multi-file).