{"record":{"id":"af1839cda3c5f91e","repo":"vercel/next.js","slug":"specified-images-remotepatterns-must-have-protocol","errorCode":null,"errorMessage":"Specified images.remotePatterns must have protocol \"http\" or \"https\" received \"${proto}\".","messagePattern":"Specified images\\.remotePatterns must have protocol \"http\" or \"https\" received \"(.+?)\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/next/src/server/config.ts","lineNumber":710,"sourceCode":"        },\n      ]\n    }\n\n    if (images.remotePatterns) {\n      if (!Array.isArray(images.remotePatterns)) {\n        throw new Error(\n          `Specified images.remotePatterns should be an Array received ${typeof images.remotePatterns}.\\nSee more info here: https://nextjs.org/docs/messages/invalid-images-config`\n        )\n      }\n\n      // We must convert URL to RemotePattern since URL has a colon in the protocol\n      // and also has additional properties we want to filter out. Also, new URL()\n      // accepts any protocol so we need manual validation here.\n      images.remotePatterns = images.remotePatterns.map(\n        ({ protocol, hostname, port, pathname, search }) => {\n          const proto = protocol?.replace(/:$/, '')\n          if (!['http', 'https', undefined].includes(proto)) {\n            throw new Error(\n              `Specified images.remotePatterns must have protocol \"http\" or \"https\" received \"${proto}\".`\n            )\n          }\n          return {\n            protocol: proto as 'http' | 'https' | undefined,\n            hostname,\n            port,\n            pathname,\n            search,\n          }\n        }\n      )\n\n      // static images are automatically prefixed with assetPrefix\n      // so we need to ensure _next/image allows downloading from\n      // this resource\n      if (config.assetPrefix?.startsWith('http')) {\n        try {","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/config.ts#L692-L728","documentation":"Each entry in `images.remotePatterns` may have `protocol` set to 'http', 'https', or omitted (undefined). The normalizer at config.ts:706-713 strips a trailing ':' then rejects any other value, because `new URL()` would accept arbitrary schemes (ftp:, file:, data:) that the image optimizer must not proxy. This is a security boundary check.","triggerScenarios":"Supplying `protocol: 'ftp'`, `protocol: 'file'`, `protocol: 'data'`, or a malformed value like `protocol: 'http//'` in a remotePattern.","commonSituations":"Copy-pasting a URL scheme from an asset link that isn't HTTP(S). Using an older config that allowed looser values. Typos such as `protcol` leaving protocol derived from another source.","solutions":["Set protocol to 'https' (preferred) or 'http': `{ protocol: 'https', hostname: 'cdn.example.com' }`.","Omit protocol entirely if the default ('https' behavior) is acceptable.","Double-check there is no trailing colon: use `'https'` not `'https:'`."],"exampleFix":"// before\nmodule.exports = { images: { remotePatterns: [{ protocol: 'ftp', hostname: 'cdn.example.com' }] } }\n// after\nmodule.exports = { images: { remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }] } }","handlingStrategy":"validation","validationCode":"const allowed = ['http', 'https', undefined];\nfor (const p of config.images?.remotePatterns ?? []) {\n  const proto = (p.protocol ?? '').replace(/:$/, '');\n  if (proto !== '' && !['http', 'https'].includes(proto)) throw new Error('invalid protocol: ' + proto);\n}","typeGuard":"function isValidProtocol(p: unknown): p is 'http' | 'https' | undefined {\n  return p === undefined || p === 'http' || p === 'https' || p === 'http:' || p === 'https:';\n}","tryCatchPattern":null,"preventionTips":["Only ever set protocol to 'https' (preferred) or 'http'.","Never copy a scheme like 'ftp://' from an asset link into a remotePattern."],"tags":["config","images","remotepatterns","security","next-config"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}