Skip to content

[recovery] Next.js image optimizer 400: "The requested resource isn't a valid image" on remote images #18796

Description

@pettinarip

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.jsimages.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:

  1. 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).
  2. 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.
  3. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐛Something isn't workingdev requiredThis requires developer resourcesrecovery-agentCreated by the Recovery Agent

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions