{"record":{"id":"e7552e75cce05463","repo":"vercel/next.js","slug":"specified-images-loaderfile-does-not-exist-at-a","errorCode":null,"errorMessage":"Specified images.loaderFile does not exist at \"${absolutePath}\".","messagePattern":"Specified images\\.loaderFile does not exist at \"(.+?)\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/next/src/server/config.ts","lineNumber":797,"sourceCode":"\n    // Append trailing slash for non-default loaders and when trailingSlash is set\n    if (\n      images.path &&\n      !images.path.endsWith('/') &&\n      (images.loader !== 'default' || result.trailingSlash)\n    ) {\n      images.path += '/'\n    }\n\n    if (images.loaderFile) {\n      if (images.loader !== 'default' && images.loader !== 'custom') {\n        throw new Error(\n          `Specified images.loader property (${images.loader}) cannot be used with images.loaderFile property. Please set images.loader to \"custom\".`\n        )\n      }\n      const absolutePath = join(dir, images.loaderFile)\n      if (!existsSync(absolutePath)) {\n        throw new Error(\n          `Specified images.loaderFile does not exist at \"${absolutePath}\".`\n        )\n      }\n      images.loaderFile = absolutePath\n    }\n  }\n\n  warnCustomizedOption(\n    result,\n    'experimental.esmExternals',\n    true,\n    'experimental.esmExternals is not recommended to be modified as it may disrupt module resolution',\n    configFileName,\n    silent\n  )\n\n  warnOptionHasBeenMovedOutOfExperimental(\n    result,","sourceCodeStart":779,"sourceCodeEnd":815,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/config.ts#L779-L815","documentation":"When `images.loaderFile` is set, Next.js resolves it relative to the project dir via `join(dir, images.loaderFile)` and checks existence with `existsSync` (config.ts:795-800). If the file is missing it throws, because the loader resolution happens at build time and a missing file would produce a broken image pipeline. The resolved absolute path is shown in the message.","triggerScenarios":"Setting `loaderFile: './src/loaders/my-loader.js'` when the file does not exist or the path is misspelled. Also fires if the file was deleted after the config was written, or the working directory differs.","commonSituations":"Renaming/moving the loader file without updating config. Using an absolute-looking path that resolves against an unexpected dir. Case-sensitivity mismatches on Linux after developing on macOS/Windows.","solutions":["Verify the file exists at the printed absolute path with `ls <path>`.","Correct the loaderFile value to a relative path from the project root that resolves to the file.","On case-sensitive filesystems, ensure the casing in loaderFile matches the actual filename exactly."],"exampleFix":"// before (file at ./src/image-loader.ts)\nmodule.exports = { images: { loader: 'custom', loaderFile: './loaders/my-loader.ts' } }\n// after\nmodule.exports = { images: { loader: 'custom', loaderFile: './src/image-loader.ts' } }","handlingStrategy":"validation","validationCode":"const fs = require('fs'); const path = require('path');\nif (config.images?.loaderFile) {\n  const abs = path.join(__dirname, config.images.loaderFile);\n  if (!fs.existsSync(abs)) throw new Error('loaderFile missing at ' + abs);\n}","typeGuard":"function loaderFileExists(dir: string, rel: unknown): boolean {\n  if (typeof rel !== 'string') return false;\n  try { return require('fs').existsSync(require('path').join(dir, rel)); } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Resolve loaderFile with an absolute path in tests to catch typos early.","On case-sensitive CI, ensure filename casing matches exactly."],"tags":["config","images","loaderfile","filesystem","next-config"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}