#Getting Bad request for images on fresh install seeding db

36 messages · Page 1 of 1 (latest)

kind pilot
night breach
#

Based on the files you shared in the general chat, I don't see why it's adding the /file. Can you confirm which template you're using @kind pilot ?

kind pilot
#

website

#

just fresh installed payload with website template then seeded the db

night breach
#

Trying to think what can be causing this. Let me Claude investigate it for a little

kind pilot
#

can you let me know if you are having the same issue on fresh install ?

#

btw i choose sqlite

night breach
#

I didn't try that right now, but I set up the website tempalte a few days ago and it works as expected.

#

So, Claude just confirmed the /file is supposed to be there, unless you're using a cloud storage plugin. That's why I had never seen that...I usually use Cloudflare R2 or AWS S3. So that doesn't seem to be the problem

#
The /file/ in media URLs is expected behavior, not a bug

  When the Payload website template seeds the database without a cloud storage plugin, Payload's core constructs URLs using its internal file-serving endpoint:

  {serverURL}/api/{collectionSlug}/file/{filename}

  e.g. http://localhost:3000/api/media/file/image-post1.webp

  Why it works this way

  In packages/payload/src/uploads/generateFilePathOrURL.ts, Payload builds the URL as:

  path: `/${collectionSlug}/file/${encodeURIComponent(filename)}`

  The /file/:filename route is registered in Payload's upload endpoints and acts as a proxied access-control layer — it allows Payload to intercept file requests and enforce access
  control before serving files from the local filesystem.

  The seed script isn't doing anything wrong

  In templates/website/src/endpoints/seed/index.ts, images are created with payload.create({ collection: 'media', file: ... }). Payload's beforeChange hook on every upload collection
  stores a relative path like /api/media/file/image-post1.webp, and the afterRead hook expands it to a full URL on read. The seed is just triggering normal Payload upload behavior.

  When does /file/ disappear?

  Only when using a cloud storage plugin (S3, R2, GCS, etc.) with a custom generateFileURL function. The cloud plugin replaces the default URL hooks and returns a CDN URL directly — no
  /file/ segment. Your project does this via generateFileURLFn → ${R2_PUBLIC_URL}/${key}.

  So your friend is seeing correct behavior — the website template uses local filesystem storage by default, and /file/ is just Payload's file-serving route. If they want clean CDN
  URLs, they need to add a cloud storage plugin.
kind pilot
#

but with blank template there is no image just initiate with website template and sqlite db and let me know

#

i can fix it with claude but i want to know why there is this issue on the fresh install at all

kind pilot
#

Disable Image Optimization for Local Dev (Recommended)
Since this is a fresh install and you're just trying to get the template running, the easiest way to stop the error is to tell Next.js not to optimize images when you're on localhost. This bypasses the proxy entirely and serves the image directly from Payload's static folder.

In your next.config.ts, add the unoptimized flag:

TypeScript
const nextConfig: NextConfig = {
images: {
**unoptimized: process.env.NODE_ENV === 'development', **// Add this line
qualities: [100],
// ... rest of your images config
},
// ... rest of config
}

#

Temporary fix

night breach
#

I was working on something else and I just noticed that "file" is added once I add a serverURL to the payload.config file 😆 . So it might be related to that.

calm stratus
#

this is a nextjs16 related issue

#

we're looking into this now and will release a fix as needed

night breach
#

@calm stratus , I'm using Nextjs15. Should it affect it somehow?

#

Let me rephrase it: once you push an update to that, should I worry about it, since I'm using nextjs 15 and see that URL is saved in the database as /api/images/file/<filename>?

calm stratus
#

If you are not using a storage adapter /api/media/file/ is the expected path for media items

#

if that's what you're asking

#

that has not changed and will not change regardless of next15 or 16

night breach
#

I am using the @payloadcms/storage-s3 adapter and files are being uploaded with the /api/media/file/path to my database (see image below). What I'm asking is if this will continue like that after the mentioned fix, or if I would need to remove that /file from the already uploaded files from my database once that happens.

calm stratus
#

what do your paths look like in production?

#

like can you validate those files are actually in your s3 bucket?

night breach
#

Yep, it's in prod. The path is images/placeholder-hero.png (images comes from the prefix I set in payload.config). It's in the bucket and it's properly rendered in the site (see the image in the previous message).

#

Just for context: this is a production environment, but there's not a lot of data since we just shared access.

#

And just to make it clear, everything works as expected:

  • The bucket has the images/placeholder-hero.png path.
  • The database saves the url as /api/images/file/placeholder-hero.png.
  • The REST API returns the full url with the domain (I have serverURL set in payload.config): https://mydomain.org/api/images/file/placeholder-hero.png.
  • Once I hit the URL, the backend returns the proper image from the bucket.

The only thing that caught my attention was the fact it adds that /file path.

calm stratus
#

this will not affect your paths

#

because you're using S3 and not disabling Payload's access control, Payload intercepts the request, fetches the file from S3, and streams it back

#

the only time that segment would change is if you use construct a custom generateFileURL to get a direct CDN url

#

does that make sense?

quasi skiff
#

hello,
when I installed fresh webtemplate the images didn't work for me too ,
I used claude code to fix the issue and I got this

#temp-nextjs-16 message

calm stratus
#

we already pushed a fix for this that will go out with the next release! 🎉

#

next15 allowed the way we handled paths, next 16 does not, simple fix