Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Optional Catchall Routes with overlapping patterns fails to correctly fall-back in dev mode #17367

Open
bits-by-brandon opened this issue Sep 25, 2020 · 9 comments
Labels
good first issue Easy to fix issues, good for newcomers Navigation Related to Next.js linking (e.g., <Link>) and navigation.
Milestone

Comments

@bits-by-brandon
Copy link
Contributor

Bug report

Describe the bug

While next is in dev mode, it fails to build appropriate catchall route when multiple catchalls exist with overlapping patterns. For example, a page at pages/[[...foo]].js/ will not be built if pages/[bar]/[[...bazz.js]] exists, until first navigating to the homepage / to force a build of [[...foo]]

To Reproduce

Created an example branch with this behavior
https://github.com/brandondc741/next-catchall-route-bug

Repro steps are located in https://github.com/brandondc741/next-catchall-route-bug/blob/master/HOW_TO_REPLICATE_ISSUE.md

  1. npx next dev
  2. First visit /foo/root
  3. Observe 404
  4. visit /
  5. Observe page renders, [[...slug]] builds
  6. visit /foo/root
  7. Observe page now renders

Expected behavior

In dev mode, when next.js is given the path /foo/root it should

  1. Attempt to render pages/[firstSegment]/[[...nestedSlug]].js
  2. Fall-back to attempting to render [[...slug]].js

System information

  • OS: macOS
  • Version of Next.js: 9.5.3
  • Version of Node.js: 12.18.0
@lfades
Copy link
Member

lfades commented Sep 26, 2020

The bug you're describing is the expected behavior, and there's no fallback behavior on routes. pages/[firstSegment]/[[...nestedSlug]].js has a higher priority than pages/[[...slug]].js. You can read more about that here: https://nextjs.org/docs/routing/dynamic-routes#caveats

Because dynamic routes have precedence over catch all routes, pages/[firstSegment]/[[...nestedSlug]].js will always match /foo/root, if that path is not defined by getStaticPaths it will render a 404 but it will never try on a different route.

@lfades lfades closed this as completed Sep 26, 2020
@bits-by-brandon
Copy link
Contributor Author

bits-by-brandon commented Sep 27, 2020

@lfades Thanks for taking a look at this issue!

If the expected behavior is as described

pages/[firstSegment]/[[...nestedSlug]].js will always match /foo/root

The we are not experiencing this behavior, and we are seeing inconsistency in how Next.js behaves. Running next dev, we see:

/foo/root -> 404
Visiting another route
/foo/root -> pages/[firstSegment]/[[...nestedSlug]].js

And during build, we see
/foo/root -> pages/[firstSegment]/[[...nestedSlug]].js

Which is both not following the behavior described, and also inconsistent. I think this is still an issue worth addressing

@lfades
Copy link
Member

lfades commented Sep 28, 2020

@brandondc741 I'm not sure I follow, during build the 404 page is only generated once.

@bits-by-brandon
Copy link
Contributor Author

@lfades Following the repro steps provided will make the issue clear: Here is a video of the behavior.

catchall-bug

@lfades lfades reopened this Sep 28, 2020
@lfades lfades added good first issue Easy to fix issues, good for newcomers kind: bug labels Sep 28, 2020
@fakeharahman
Copy link

Hey, I am new to open source. Can I try to work on this issue?

@bits-by-brandon
Copy link
Contributor Author

@fakeharahman I haven't done any work investigating this one yet, so go ahead and take a look!

@Timer Timer added this to the backlog milestone Jan 6, 2021
@timneutkens timneutkens added the Navigation Related to Next.js linking (e.g., <Link>) and navigation. label Nov 18, 2021
@maidi29
Copy link

maidi29 commented Sep 22, 2022

I'm experiencing a similar issue. I have the following structure

pages/foo/[...slug].tsx
pages/[[...slug]].tsx

In the catchAllRoute of [[...slug]].tsx in the root, there exists a page foo/xy that is not covered by the filter in getStaticPaths of the [...slug].tsx inside foo. In the dev mode the application runs into an error calling foo/xy. With build and start it works fine on the first call but when revalidate fires, the error is still there.

We managed to identify the possible cause of this bug:
When running in the dev mode getStaticPaths is "ignored" because there is no static generation --> the call arrives in [slug].tsx inside foo and jumps into getStaticProps and tries to render the page from there without looking it up in [[...slug]].tsx in the root.
While building, getStaticPaths is taken into account and everything renders as it should. Then (in our case) revalidate fires and again we directly jump into getStaticProps of the [...slug].tsx inside foo.

A fix of this bug should consider the overlapping catchAllRoutes based on their filter in getStaticPaths also in revalidate and dev mode.

@apfelbox
Copy link

apfelbox commented Jan 16, 2023

I have the same issue:

/[[...url]].tsx
/test/[[...url]].tsx

will always call the first route in dev mode, no matter what the URL is.

In Next 12, this also doesn't work:

/[[...url]].tsx
/test/[...url].tsx

@jiggy1com
Copy link

jiggy1com commented May 16, 2023

@apfelbox (@bits-by-brandon) Try this:

pages/[...slug].js 
pages/test/[[...slug]].js

Should result in:

/random-page                  // context.query.slug = ['random-page']
/test                         // context.query.slug = undefined 
/test/another-random-page     // context.query.slug = ['another-random-page']

UPDATE:
Oops! I forgot to add something (because I had a rewrite in next.config.js to change / to /home which allowed pages/[...slug] to pick it up)

So, in addition to the above ^^^ you can do either of these:

// Option 1 - Use pages/index.js
import PageWildCard from "pages/[...slug]";
import {getServerSideProps} from 'pages/[...slug]';

module.exports = {
    default: PageWildCard,
    getServerSideProps: getServerSideProps
}

or

// Option 2 - Use a rewrite (do not create pages/index.js)
// inside next.config.js 
async rewrites() {
    return [
      {
        source: '/',
        destination: '/your-desired-home-route',
      }, 
    ]
},

See https://nextjs.org/docs/pages/api-reference/next-config-js/rewrites for more info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Easy to fix issues, good for newcomers Navigation Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

No branches or pull requests

9 participants