serverless-next.js: Catch-all at /pages root breaks static file serving
Describe the bug
Next supports having a catch-all route at pages/[...all] (this works with next start). However, when I add this file (with getStaticPaths fallback: true) and deploy using serverless-next.js, requests for static assets break.
Actual behavior
Assets don’t load
- in some cases, they 503
- in other cases, it seems requests for static data are handled by
pages/[...all](next’s fallback rendering). This results in a 200 with type text/html. I can paste these asset URLs in my browser and get the fallback page.
This applies to all kinds of assets (next’s /_next files as well as things in public/).
Expected behavior
Static files are served correctly.
Steps to reproduce
Add a catch-all route at pages/[...all] with getStaticPaths. (I haven’t tested this with SSR)
Versions
- OS/Environment: Mac
- @sls-next/serverless-component version: 1.17.0
- next: 9.4.4
Other info
When I add fallback: false the requests become 503s, but otherwise the issue is the same.
Does serverless-next.js support this? I couldn’t find mention in the documentation, sorry if I missed something. It makes sense that this would be tricky, but wondering if there’s a known workaround.
If this is unsupported, is there a roadmap or further discussion on this? This is very high-value to my team, as it would unlock the ability to define any URL path using CMS.
ETA:
- If it’s helpful, my cloudwatch logs are full of this error

- Also, I tried this with a dynamic, non-catch-all route (
pages/[all]) and it still breaks forpublic/test.png, but no longer breaks forpublic/assets/test.pngor for/_nextassets. This seems to confirm the rule that assets URLs can’t match/pagespatterns.
My solution for now is to both a) use [all] for content pages (ie limit created pages to one path segment), and b) require everything in public to be in public/assets so they don’t match [all]
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 33
Okay so it’s an error on my part and I have to apologize. The docs have to be followed strictly
The mistake I made was I referenced my favicon which was located in
public/assets/favicon.icobyassets/favicon.icowhich works for non-catch-all routes but not for catch-all routes. The correct way to write it would be/assets/favicon.ico. I hope whoever sees this finds it useful!Hey @dphang my bad, was testing out a fix I made to lambda-at-edge, which I deployed to the demo.
https://github.com/himynameistimli/serverless-next.js/blob/6c966fdc6ed0b6909b164126cd58e8d5c20c5799/packages/libs/lambda-at-edge/src/default-handler.ts#L576-L583
It fixes it for my specific use case, but that’s because I don’t make use of fallbacks for SSG pages. I copied the repro manifests into a fiddle to see what was happening. https://jsfiddle.net/sbpxqeft/.
hasFallbackForUriwill return a different prerendered dynamic route (for an SSG page) if it has a more generalized regex that also happens to to work with a dynamic SSR route.So I essentially told it to ignore the fallback if there is a dynamic SSR route that also matches. I don’t know if this is generally right, but I think that there should be some check between the manifest and the prerenderManifest to make sure that they are talking about the same route.
I will restore the demo back to the latest beta. Sorry for the confusion.
I see, I added rewrites to the e2e-test next app here:
When I added the first rewrite, the
next devserver is only matching the 1st rewrite for me, hence in that app it goes to a catch all page I defined at the root. If I remove the first one, then any path is rewritten tossg-pageand it’s served correctly - an SSG page. This seemed to be same behavior on both Next.js dev server and serverless-next.js. Although this is Next.js 9.5.5, not sure if something changed with the later versions.Anyway, so I thought that first no-op rewrite is only needed when you are proxying to another domain, which I hadn’t implemented yet. But the way it’s implemented now, it doesn’t know about this special no-op rewrite; the first rewrite will get matched. I think there are a few things to fix:
BTW, do you have a minimal repro you can create and share? It will make it easier to debug and fix the specific scenario(s) you have in mind. Since in this case it looks like multiple things (catch-all, public files, SSR/SSG pages, rewrites) are interacting with each other, it may be hard for me to repro just via descriptions.
Thanks!
Thanks, I will take a look at this this week.
I think this component should support it according to features list but I believe catch-all and
getStaticPathswere each implemented separately, perhaps there’s a bug when both are used.