Skip to content

fix: resolve 404/500 error when downloading files containing hash in filename#15799

Merged
paulpopus merged 5 commits into
payloadcms:mainfrom
andershermansen:issue-15798-filename-with-hash
Apr 2, 2026
Merged

fix: resolve 404/500 error when downloading files containing hash in filename#15799
paulpopus merged 5 commits into
payloadcms:mainfrom
andershermansen:issue-15798-filename-with-hash

Conversation

@andershermansen

@andershermansen andershermansen commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

What?

Fixes file downloads returning 404 for filenames containing # when served through the REST API.

Why?

Next.js catch-all [...slug] params decodes URL-encoded segments before passing them for further handling. So a request for /api/media/file/document%20%23123.pdf arrives with slug segments ['media', 'file', 'document #123.pdf'].

These decoded segments are joined and passed to handleEndpoints, but the implementation of handleEndpoints is using path-to-regexp with a configuration that expectes urlencoded path segments.

How?

Re-encode each slug segment with encodeURIComponent before joining:

handleEndpoints already uses match(endpoint.path, { decode: decodeURIComponent }), so params are decoded back to their original values after matching

Also adds a test that creates a file with # in the filename and verifies it can be served via REST.

Fixes #15798

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes REST file downloads returning 404 when filenames contain # by ensuring Next.js-decoded catch-all slug segments are re-encoded before route matching.

Changes:

  • Re-encode each [...slug] segment with encodeURIComponent before joining into the REST handler path
  • Add an integration test covering uploads/downloads where the stored filename contains #

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
test/uploads/int.spec.ts Adds an integration test asserting files with # in the filename can be fetched via the REST file endpoint
packages/next/src/routes/rest/index.ts Re-encodes decoded slug segments so path-to-regexp endpoint matching works with #/? in filenames

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/uploads/int.spec.ts
@andershermansen

andershermansen commented Mar 3, 2026

Copy link
Copy Markdown
Contributor Author

Alternative solution in #15823

@andershermansen andershermansen changed the title fix: re-encode Next.js decoded slug segments in REST route handler fix: resolve 404/500 error when downloading files containing hash in filename Apr 2, 2026
@paulpopus paulpopus merged commit 3a09387 into payloadcms:main Apr 2, 2026
157 checks passed
@andershermansen andershermansen deleted the issue-15798-filename-with-hash branch April 2, 2026 17:28
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

🚀 This is included in version v3.82.0

milamer pushed a commit to milamer/payload that referenced this pull request Apr 20, 2026
…filename (payloadcms#15799)

### What?

Fixes file downloads returning 404 for filenames containing `#` when
served through the REST API.

 ### Why?

Next.js catch-all `[...slug]` params decodes URL-encoded segments before
passing them for further handling. So a request for
`/api/media/file/document%20%23123.pdf` arrives with slug segments
`['media', 'file', 'document payloadcms#123.pdf']`.

These decoded segments are joined and passed to handleEndpoints, but the
implementation of handleEndpoints is using `path-to-regexp` with a
configuration that expectes urlencoded path segments.

### How?

Re-encode each slug segment with `encodeURIComponent` before joining:

handleEndpoints already uses match(endpoint.path, { decode:
decodeURIComponent }), so params are decoded back to their original
values after matching

Also adds a test that creates a file with # in the filename and verifies
it can be served via REST.

Fixes payloadcms#15798

---------

Co-authored-by: Paul Popus <paul@payloadcms.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

REST API returns 404 for filenames containing # (hash character)

3 participants