Skip to content

Cannot edit image when serverURL is set #14945

@jefferyto

Description

@jefferyto

Describe the Bug

Following the reproduction steps below, this is the error I get:

[23:59:21] ERROR: There was a problem while uploading the file. Blocked unsafe attempt to localhost
    err: {
      "type": "FileRetrievalError",
      "message": "There was a problem while uploading the file. Blocked unsafe attempt to localhost",
      "stack":
          FileRetrievalError: There was a problem while uploading the file. Blocked unsafe attempt to localhost
              at generateFileData (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/uploads/generateFileData.js:72:19)
              at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
              at async updateByIDOperation (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/collections/operations/updateByID.js:94:61)
              at async updateByIDHandler (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/collections/endpoints/updateByID.js:9:17)
              at async handleEndpoints (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/utilities/handleEndpoints.js:191:26)
              at async eval (webpack-internal:///(rsc)/./node_modules/@payloadcms/next/dist/routes/rest/index.js:30:20)
              at async AppRouteRouteModule.do (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:5:38782)
              at async AppRouteRouteModule.handle (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:5:45984)
              at async responseGenerator (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:206:38)
              at async AppRouteRouteModule.handleResponse (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:1:183692)
              at async handleResponse (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:268:32)
              at async handler (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:320:13)
              at async doRender (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1592:34)
              at async DevServer.renderToResponseWithComponentsImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1934:13)
              at async DevServer.renderPageComponent (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:2400:24)
              at async DevServer.renderToResponseImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:2440:32)
              at async DevServer.pipeImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1035:25)
              at async NextNodeServer.handleCatchallRenderRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/next-server.js:393:17)
              at async DevServer.handleRequestImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:925:17)
              at async /home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/dev/next-dev-server.js:398:20
              at async Span.traceAsyncFn (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/trace/trace.js:157:20)
              at async DevServer.handleRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/dev/next-dev-server.js:394:24)
              at async invokeRender (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:239:21)
              at async handleRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:436:24)
              at async requestHandlerImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:464:13)
              at async Server.requestListener (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/start-server.js:218:13)
      "data": null,
      "isOperational": true,
      "isPublic": false,
      "status": 500,
      "name": "FileRetrievalError"
    }
 PATCH /api/media/1?depth=0&fallback-locale=null&uploadEdits%5Bcrop%5D%5Bunit%5D=%25&uploadEdits%5Bcrop%5D%5Bx%5D=0&uploadEdits%5Bcrop%5D%5By%5D=0&uploadEdits%5Bcrop%5D%5Bwidth%5D=74.56&uploadEdits%5Bcrop%5D%5Bheight%5D=77&uploadEdits%5BfocalPoint%5D%5Bx%5D=50&uploadEdits%5BfocalPoint%5D%5By%5D=50&uploadEdits%5BheightInPixels%5D=231&uploadEdits%5BwidthInPixels%5D=466 500 in 856ms

If I set serverURL to "http://127.0.0.1:3000", I get a slightly different error message:

[00:14:44] ERROR: There was a problem while uploading the file. Failed to fetch from http://127.0.0.1:3000/api/media/file/featured-image-cycling-in-hong-kong.jpg, Blocked unsafe attempt to 127.0.0.1
    err: {
      "type": "FileRetrievalError",
      "message": "There was a problem while uploading the file. Failed to fetch from http://127.0.0.1:3000/api/media/file/featured-image-cycling-in-hong-kong.jpg, Blocked unsafe attempt to 127.0.0.1",
      "stack":
          FileRetrievalError: There was a problem while uploading the file. Failed to fetch from http://127.0.0.1:3000/api/media/file/featured-image-cycling-in-hong-kong.jpg, Blocked unsafe attempt to 127.0.0.1
              at generateFileData (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/uploads/generateFileData.js:72:19)
              at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
              at async updateByIDOperation (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/collections/operations/updateByID.js:94:61)
              at async updateByIDHandler (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/collections/endpoints/updateByID.js:9:17)
              at async handleEndpoints (file:///home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/payload/dist/utilities/handleEndpoints.js:191:26)
              at async eval (webpack-internal:///(rsc)/./node_modules/@payloadcms/next/dist/routes/rest/index.js:30:20)
              at async AppRouteRouteModule.do (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:5:38782)
              at async AppRouteRouteModule.handle (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:5:45984)
              at async responseGenerator (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:206:38)
              at async AppRouteRouteModule.handleResponse (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:1:183692)
              at async handleResponse (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:268:32)
              at async handler (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.js?name=app%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&page=%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute&appPaths=&pagePath=private-next-app-dir%2F(payload)%2Fapi%2F%5B...slug%5D%2Froute.ts&appDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2Fhome%2Fjeff%2FCode%2Fpersonal%2Fpayload%2Fissues%2Fserver-url-edit-image-blocked-unsafe-attempt&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=&preferredRegion=&middlewareConfig=e30%3D&isGlobalNotFoundEnabled=!:320:13)
              at async doRender (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1592:34)
              at async DevServer.renderToResponseWithComponentsImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1934:13)
              at async DevServer.renderPageComponent (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:2400:24)
              at async DevServer.renderToResponseImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:2440:32)
              at async DevServer.pipeImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:1035:25)
              at async NextNodeServer.handleCatchallRenderRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/next-server.js:393:17)
              at async DevServer.handleRequestImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/base-server.js:925:17)
              at async /home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/dev/next-dev-server.js:398:20
              at async Span.traceAsyncFn (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/trace/trace.js:157:20)
              at async DevServer.handleRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/dev/next-dev-server.js:394:24)
              at async invokeRender (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:239:21)
              at async handleRequest (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:436:24)
              at async requestHandlerImpl (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/router-server.js:464:13)
              at async Server.requestListener (/home/jeff/Code/personal/payload/issues/server-url-edit-image-blocked-unsafe-attempt/node_modules/next/dist/server/lib/start-server.js:218:13)
      "data": null,
      "isOperational": true,
      "isPublic": false,
      "status": 500,
      "name": "FileRetrievalError"
    }
 PATCH /api/media/1?depth=0&fallback-locale=null&uploadEdits%5Bcrop%5D%5Bunit%5D=%25&uploadEdits%5Bcrop%5D%5Bx%5D=29.280397022332505&uploadEdits%5Bcrop%5D%5By%5D=0&uploadEdits%5Bcrop%5D%5Bwidth%5D=70.71960297766749&uploadEdits%5Bcrop%5D%5Bheight%5D=100&uploadEdits%5BfocalPoint%5D%5Bx%5D=50&uploadEdits%5BfocalPoint%5D%5By%5D=50&uploadEdits%5BheightInPixels%5D=105&uploadEdits%5BwidthInPixels%5D=285 500 in 164ms

Payload appears to be treating local image edits as if they are remote file accesses.

This appears to be a continuation of #12876 (ping @kendelljoseph) - it appears some of that issue's commenters were experiencing this issue.

A workaround is to add Payload's server details to skipSafeFetch for the upload collection, e.g.:

  upload: {
    skipSafeFetch: [
      {
        hostname: 'localhost',
        port: '3000',
        protocol: 'http',
      },
    ],
  },

Link to the code that reproduces this issue

https://github.com/jefferyto/payload-serverURL-edit-image-blocked-unsafe-attempt

Reproduction Steps

  1. Checkout reproduction repo (note that serverURL in src/payload.config.ts is set to "http://localhost:3000"), npm install, npm run dev
  2. Open http://localhost:3000/admin, create first user, upload an image
  3. Edit the image (click "Edit Image", change cropping, click "Apply Changes") and attempt to save the edited image

Which area(s) are affected?

area: core

Environment Info

Binaries:
  Node: 24.11.1
  npm: 11.6.4
  Yarn: 1.22.22
  pnpm: 10.26.0
Relevant Packages:
  payload: 3.68.5
  next: 15.4.10
  @payloadcms/db-sqlite: 3.68.5
  @payloadcms/drizzle: 3.68.5
  @payloadcms/graphql: 3.68.5
  @payloadcms/next/utilities: 3.68.5
  @payloadcms/richtext-lexical: 3.68.5
  @payloadcms/translations: 3.68.5
  @payloadcms/ui/shared: 3.68.5
  react: 19.2.1
  react-dom: 19.2.1
Operating System:
  Platform: linux
  Arch: x64
  Version: #8-Ubuntu SMP PREEMPT_DYNAMIC Fri Nov 14 21:44:46 UTC 2025
  Available memory (MB): 7224
  Available CPU cores: 4

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions