vercel/next.js · error

Specified images.remotePatterns should be an Array received

Error message

Specified images.remotePatterns should be an Array received ${typeof images.remotePatterns}.
See more info here: https://nextjs.org/docs/messages/invalid-images-config

What it means

`images.remotePatterns` defines remote hosts _next/image is allowed to optimize and must be an array of pattern objects. The check at config.ts:696-701 rejects truthy non-arrays because the code immediately calls `.map()` over entries to normalize protocol/host/port. An unset value is fine (no remote hosts); only a wrong-typed value throws.

Source

Thrown at packages/next/src/server/config.ts:698

        // static import images are automatically allowed
        images.localPatterns.push({
          pathname: '/_next/static/immutable/media/**',
          search: '',
        })
      }
    } else {
      // All paths are not allowed for a search query by default.
      images.localPatterns = [
        {
          pathname: '**',
          search: '',
        },
      ]
    }

    if (images.remotePatterns) {
      if (!Array.isArray(images.remotePatterns)) {
        throw new Error(
          `Specified images.remotePatterns should be an Array received ${typeof images.remotePatterns}.\nSee more info here: https://nextjs.org/docs/messages/invalid-images-config`
        )
      }

      // We must convert URL to RemotePattern since URL has a colon in the protocol
      // and also has additional properties we want to filter out. Also, new URL()
      // accepts any protocol so we need manual validation here.
      images.remotePatterns = images.remotePatterns.map(
        ({ protocol, hostname, port, pathname, search }) => {
          const proto = protocol?.replace(/:$/, '')
          if (!['http', 'https', undefined].includes(proto)) {
            throw new Error(
              `Specified images.remotePatterns must have protocol "http" or "https" received "${proto}".`
            )
          }
          return {
            protocol: proto as 'http' | 'https' | undefined,
            hostname,

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Wrap remote patterns in an array: `remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }]`.
  2. Use `domains: ['cdn.example.com']` only if you need the legacy simpler form.
  3. Drop the key entirely to disable remote optimization.

Example fix

// before
module.exports = { images: { remotePatterns: { hostname: 'cdn.example.com' } } }
// after
module.exports = { images: { remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }] } }
Defensive patterns

Strategy: type-guard

Validate before calling

const rp = config.images?.remotePatterns;
if (rp != null && !Array.isArray(rp)) throw new Error('images.remotePatterns must be an array');
for (const p of rp ?? []) { if (typeof p.hostname !== 'string') throw new Error('each remotePattern needs a hostname string'); }

Type guard

type RemotePattern = { protocol?: 'http' | 'https'; hostname: string; port?: string; pathname?: string; search?: string };
function isRemotePatternsArray(v: unknown): v is RemotePattern[] {
  return Array.isArray(v) && v.every((p) => p && typeof (p as any).hostname === 'string');
}

Prevention

When it happens

Trigger: Setting `images: { remotePatterns: { hostname: 'cdn.com' } }` (single object) or `remotePatterns: 'cdn.com'` (string).

Common situations: Confusing remotePatterns (array of structured objects) with the deprecated `domains` (array of strings). Copying a single example object from docs without wrapping it in `[ ]`.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/26f1eee95c606131. Report an issue: GitHub.