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

Parallel / Intercepting Routes rendering 404 on page load #48289

Closed
1 task done
tommyboylab opened this issue Apr 12, 2023 · 27 comments
Closed
1 task done

Parallel / Intercepting Routes rendering 404 on page load #48289

tommyboylab opened this issue Apr 12, 2023 · 27 comments
Labels
bug Issue was opened via the bug report template. locked

Comments

@tommyboylab
Copy link

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.4.0: Mon Mar  6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.13.0
      npm: 9.4.0
      Yarn: 1.22.19
      pnpm: N/A
    Relevant packages:
      next: 13.3.1-canary.4
      eslint-config-next: 13.3.0
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

No response

Link to the code that reproduces this issue

https://vercelnextjsnzcvbl-dh2v--3000--b5037fed.local-credentialless.webcontainer.io/1

To Reproduce

  • Create a Intercepting / Parallel route layout within the app directory
  • Add a modal with a dynamic page (ex: @modal/[id]) with a console log
  • Add a parent page for the same path (ex: [id]) with a console log
  • Attempt to navigate to the dynamic page and see the modal is rendered
  • Refresh the page and see you have a 404 rendered, while the console log for parent page has been called

Describe the Bug

Upon initial client-side navigation to an intercepted route, the page is properly navigated and modal is shown. Upon reloading the page the content is not rendered, get a 404 page but params are still passed.

next-route

Expected Behavior

Navigation should first show modal on initial load from top level page. After reloading the parent page should be loaded, not have 404 but still receive props

The intention is to have a blog page with a list of articles with a set of ids (a,b,c..) which are conditionally rendered in a modal while on the blog page itself, are rendered standalone when visiting from a link / page is reloaded.

blog
├── @modal/[id]
│   └── page.tsx
├── @list
│   └── page.tsx
└── layout.tsx
├── [id]
     └── page.tsx

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

@tommyboylab tommyboylab added the bug Issue was opened via the bug report template. label Apr 12, 2023
@Fredkiss3
Copy link
Contributor

Fredkiss3 commented Apr 13, 2023

the link to the reproduction code is broken. can you update it ?

@Nickman87
Copy link

@Fredkiss3 I am having similar issues so I tried to build a reproduction codebase here: https://codesandbox.io/p/sandbox/nextjs-intercepting-routes-s9j6mo

If you click open blog you go to the blog page, and there you can open a blog item, but clicking that just redirects to the actual blog page, and not just the modal. (it also renders both the blog page AND the modal, which is strange).

Not sure if this is the exact problem he is describing, because I also have an issue with a 404 locally, but cannot reproduce right now in a codesandbox.

@Nickman87
Copy link

Nickman87 commented Apr 28, 2023

@feedthejim I think there is still something wrong with the (.) selector (#48276):
If you check out this repo: https://codesandbox.io/p/sandbox/nextjs-intercepting-routes-s9j6mo
You will see that if you open the blog post, there are two things happening that are off:

  1. It also loads the intercepted page als main page (it replaces the blog page with the item page)
  2. If you have the blog post modal open and refresh the page, it will give you a 404

I modified this repo to use the old (..) syntax here: https://codesandbox.io/p/sandbox/nextjs-intercepting-routes-forked-bfuitc
If you try this version (only change is (.) became (..)blog and I also placed everything into a (group)), then everything works as expected.

@Nickman87
Copy link

Maybe related to #48090 ?

@conmute
Copy link

conmute commented Jun 12, 2023

I have some similar issue… When I have:

// ✅ Should intercept <Link> route navigation and display the my modal but do not show the `/create/note` page
src/app/@modal/(.)create/note/page.tsx

// 🔴 Should render ONLY on direct url hit, as expected. But gives 404 me instead
src/app/create/note/page.tsx

// ✅ has the <Link href="/create/note">Create note<Link>
src/app/page.tsx

// ✅ has the {children} and {modal} slots to be rendered inside
src/app/layout.tsx

Everything is working, except src/app/create/note/page.tsx gives me 404

If I will change src/app/@modal/(.)create/note/page.tsx to a different path, the src/app/create/note/page.tsx will be rendered fine but then there is no interception possible this way


More details, using the example by given link in Vercel NextJS documentation: https://github.com/vercel-labs/nextgram/tree/main/app for interceptor Modal example,

and I see that @modal/(..)photos/[id] has (..) two dots in the interceptor. But this is not working in my freshly installed app, it gives me such an error:

- error unhandledRejection: Error: Invalid interception route: /(..)create/note. Cannot use (..) marker at the root level, use (.) instead.
    at extractInterceptionRouteInformation (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/app/node_modules/next/dist/server/future/helpers/interception-routes.js:64:23)
    at generateInterceptionRoutesRewrites (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/app/node_modules/next/dist/lib/generate-interception-routes-rewrites.js:41:123)
    at Watchpack.<anonymous> (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/app/node_modules/next/dist/server/dev/next-dev-server.js:587:139)

My setup package.json has "next": "13.4.4",, with @modal/(.)create/note/page.tsx with one dot I was able to intercept but not able to render after refresh targeted URL as intended

@conmute
Copy link

conmute commented Jun 12, 2023

Shortly, If I will clone https://github.com/vercel-labs/nextgram/tree/main and update npm install next@latest it will give me the same error:

> next dev

- ready started server on 0.0.0.0:3000, url: http://localhost:3000
/bin/sh: yarn: command not found
- event compiled client and server successfully in 381 ms (20 modules)
- wait compiling...
/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/tmp/node_modules/next/dist/server/future/helpers/interception-routes.js:64
                throw new Error(`Invalid interception route: ${path}. Cannot use (..) marker at the root level, use (.) instead.`);
                      ^

Error: Invalid interception route: /(..)photos/[id]. Cannot use (..) marker at the root level, use (.) instead.
    at extractInterceptionRouteInformation (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/tmp/node_modules/next/dist/server/future/helpers/interception-routes.js:64:23)
    at generateInterceptionRoutesRewrites (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/tmp/node_modules/next/dist/lib/generate-interception-routes-rewrites.js:41:123)
    at Watchpack.<anonymous> (/Users/ross/Documents/target/Conmution/playground/fireship-nextjs/tmp/node_modules/next/dist/server/dev/next-dev-server.js:587:139)

Node.js v18.15.0

the update from "next": "13.3.1-canary.1" to "next": "^13.4.5" (at current moment) will break the intercepting routes, fix and update example is necessary

@conmute
Copy link

conmute commented Jun 12, 2023

After some time, I did file move from /app folder outside and then inside everything worked well but with (.), here is now working example of intercepted routes that I have

https://github.com/conmute/fireship-nextjs/tree/main/app/src/app/%40modal

@jessepinho
Copy link

OMG — I think I've figured this out!

I was running into the same problem: the intercepted route would load fine when clicking a <Link />; but when I refreshed the page on the intercepted route, it would 404.

Here's the problem: if the layout slot isn't filled based on the current path, it will 404. You can test this by removing the slot from the layout file, and then doing a full-page load on the intercepted route path. The full-page load should work just fine now. Then, when you add the slot back to the layout file, it'll 404 again.

To fix this, you need to use a route group. Remove the slot from your root layout, and create a new layout inside your route group that just renders children and your slot:

// src/app/(home)/layout.tsx
import { ReactNode } from 'react'

export default function Layout({
  children,
  slotNameHere,
}: {
  children: ReactNode
  slotNameHere: ReactNode
}) {
  return (
    <>
      {children}
      {slotNameHere}
    </>
  )
}

Move your homepage and your intercepted routes underneath your route group:

- src
  - app
    - (home)
      - @slotNameHere
        - (.)routeName
          - page.tsx
          - ...etc

Note that, if your intercepted route is a few levels down (e.g., src/app/(home)/@slotNameHere/(.)routeName/foo/bar/page.tsx, you may need to create a page.tsx at the level right under the root of the intercepted route to prevent the same 404 issue (i.e., at src/app/(home)/@slotNameHere/(.)routeName/page.tsx). This can just be an empty component that returns null.

@kachkaev
Copy link
Contributor

I am facing a similar bug, the details are here: #53170

@jessepinho, I am unable to fix 404s with the group. Since you are saying that you have figured it out, can it be that my reproduction example is just misconfigured? If you can spot a missing bit that is causing 404s, that’ll be awesome!

@jessepinho
Copy link

@kachkaev I don't have more time to look into it, but it looks like you're using three dots in the name of your (...)photo directory, which I believe is invalid.

@kachkaev
Copy link
Contributor

kachkaev commented Jul 25, 2023

@jessepinho three dots refer to root app directory so they are fine I guess. My reproduction in #53170 works the same way for (.)photo. Thanks for looking at it anyway!

@jscul
Copy link

jscul commented Aug 17, 2023

Intercepting and parallel routes seem completely broken to me... or the docs are completely wrong. Either way, this is a very frustrating issue. The group solution did not work for me.

@joefitter
Copy link

The "trick" to this is to use default.tsx to cover non-matching slots. Adapting the example app worked for my use case

@jmarbutt

This comment was marked as off-topic.

@jmarbutt
Copy link

jmarbutt commented Sep 8, 2023

I agree with @jscul on this one, so much of this seems completely broken and half baked. The docs are not correct.

@AkshatKaushik3005
Copy link

has any fix been applied for this?

@SomervilleTom
Copy link

The "trick" to this is to use default.tsx to cover non-matching slots. Adapting the example app worked for my use case

I'm using js rather than tsx, and I have a 'default.js' (as per the documentation) in the following paths:

  • 'src/app/@modal/(..)photos'
  • 'src/app/default.js'

My hierarchy (borrowed from the "nextgram" example) is:

src/
    app/
        @modal/
            (..)photos/
                [id]/
                    page.js
            default.js
        photos/
            [id]/
                page.js
        default.js

I develop in vscode on a remote (linux) system. Here is the complaint I get in the embedded terminal of vscode
when I run "yarn dev":

Error: Invalid interception route: /(..)photos/[id]. Cannot use (..) marker at the root level, use (.) instead.
    at extractInterceptionRouteInformation (<...>/node_modules/next/dist/server/future/helpers/interception-routes.js:64:23)
    at generateInterceptionRoutesRewrites (<...>/node_modules/next/dist/lib/generate-interception-routes-rewrites.js:47:121)
    at Watchpack.<anonymous> (<...>/node_modules/next/dist/server/lib/router-utils/setup-dev.js:1346:164)

So far as I can tell, this is an issue from next.js.

According to '<...>/node_modules/next/package.json', I'm running v13.5.4.

I run the most recent Javascript version of nextgram. That uses v13.3.1-canary.1 (according to its package.json), and works as documented.

It looks to me as though v13.5.4 does not align with the documentation or the next.js example.

@kshyr
Copy link

kshyr commented Oct 10, 2023

@SomervilleTom take a look here https://github.com/vercel-labs/nextgram/tree/main/src/app/%40modal. They use (.)photos. From Next.js docs at https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes:

Note that the (..) convention is based on route segments, not the file-system.

@modal does not affect route, so they should be on one segment.

Also seems like nextgram uses v13.4.7. I just had to downgrade because I kept getting Could not find the module in the React Client Manifest. This is probably a bug in the React Server Components bundler.

@SomervilleTom
Copy link

@kshyr: Interesting. Please note that I wrote my version based on the most recent JAVASCRIPT (as opposed to tsx) version of the example.

I note that in this earlier version, the 'next.config.js' file contains the following 'experimental' entry:

    // ...
    experimental: {
        appDir: true,
    },
    // ...

I changed my code to use the single-level intercepting route ('src/app/@modal/(.)photos'). With that change, the example breaks with a different error complaint in the console (excess lines elided):

[Fast Refresh] rebuilding
Warning: Cannot update a component (`HotReload`) while rendering a different component (`Router`). To locate the bad setState() call inside `Router`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:157:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:82:9)
    at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:110:11)
    at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:440:13)
    at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:126:11)
    at RSCComponent
    at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:142:11)
Uncaught TypeError TypeError: initialTree is not iterable
    at applyPatch (<...>/node_modules/next/dist/client/components/router-reducer/apply-router-state-patch-to-tree.js:15:53)
    at applyRouterStatePatchToTree (<...>/node_modules/next/dist/client/components/router-reducer/apply-router-state-patch-to-tree.js:70:30)
    at navigateReducer (<...>/node_modules/next/dist/client/components/router-reducer/reducers/navigate-reducer.js:206:83)
    at clientReducer (<...>/node_modules/next/dist/client/components/router-reducer/router-reducer.js:25:60)
    at eval (<...>/node_modules/next/dist/client/components/use-reducer-with-devtools.js:63:21)
    at updateReducerImpl (<...>/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:11246:1)
    at updateReducer (<...>/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:11136:1)
    at useReducer (<...>/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:12554:1)
    at useReducer (<...>/node_modules/next/dist/compiled/react/cjs/react.development.js:1760:1)
    at useReducerWithReduxDevtoolsImpl (<...>/node_modules/next/dist/client/components/use-reducer-with-devtools.js:102:52)
    at Router (<...>/node_modules/next/dist/client/components/app-router.js:184:168)
    at renderWithHooks (<...>/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:10730:1)
    at updateFunctionComponent (<...>/node_modules/next/dist/compiled/react-dom/cjs/react-dom.development.js:15213:1)
...

My read of this stack trace is that the Router and useReducer code in '<..>/node_modules/next/dist' is broken.

I need modal dialogs. I guess it's time to start seeking some sort of work-around. Since the "AppRouter" functionality seems to be broken, perhaps I need either somehow code modal behavior myself, revert to the "pages" paradigm, or find a way to patch this bug.

@SomervilleTom
Copy link

SomervilleTom commented Oct 10, 2023

I spent the last several hours refactoring my version of nextgram to add an extra segment ('hack') to the "photos"/"@modal" portion.

I added 'console.log' statements to each 'page.js', to each 'default.js', and to each 'layout.js' in hopes working out what elements are actually rendered.

The result is that, as far as I can tell, the intercepting route is simply ignored.

Here is my new structure:

src/
    app/
        hack/
            @modal/
                (..)photos/
                    [id]/
                        page.js
                default.js
            photos/
                [id]/
                    page.js
            default.js
        layout.js
        page.js

The top-level 'page.js' ('src/app/page.js') contains a Link button whose href is '/hack/photos'. This opens the "nextgram' page as expected. Each item in that page is a Link whose href is 'hack/photos/${id}'. In the original nextgram example, each of those causes the intercepting route to be invoked when the item is clicked.

In this version, when one of those is clicked, the plain (non-modal) photos/[id] page is rendered.

At no time is there any evidence that any '@model' descendent is ever rendered.

It appears to me that in the v13.5.4 release, parallel/intercepting routes are either broken or do nothing.

@SomervilleTom
Copy link

I spent the rest of the afternoon trying to patch v13.4.7 (the version used in the most recent nextgram example) to use the "https" (rather than "http") protocol. The next.js code successfully resisted this attempt.

My next step is to punt the "AppRoute" approach altogether, at least for now, and revert to the less-favored "Pages" approach. I don't need to do any streaming, so perhaps this will be more fruitful.

At least for now, the APIRoute approach is a dead-end for me.

@SomervilleTom
Copy link

SomervilleTom commented Oct 11, 2023

I was finally able to get a copy of the nextgram example working on my system. It worked after I did the following (not all might be needed)

  1. Add sections to 'package.json'

    The following need to be added to "dependencies":

    "@headlessui/react": "^1.7.15",
    "clsx": "^1.2.1",
    

    A "devDependencies" apparently needs to be present:

    "devDependencies: {
        "@types/node": "20.3.1",
        "@types/react": "^18.2.14",
        "autoprefixer": "^10.4.14",
        "postcss": "^8.4.24",
        "sass": "^1.63.6",
        "tailwindcss": "^3.3.2",
        "typescript": "^5.1.3"
    },
    
  2. Add top-level config files

    • 'tsconfig.json'

    • 'postcss.config.js'

    • 'next.config.js'

      This includes the following "experimental" section:

      experimental: {
        appDir: true,
      },
      

      This is specific to 'v13.4.7' of 'next.js'

    • 'tailwind.config.js'

  3. Use explicit paths in 'app/@modal/(.)photos/[id]/page.js'

    React encourages the use of a top-level 'jsconfig.json' file that provides more convenient expressions in import statements. It appears that the '@whatever' syntax breaks that facility.

    I therefore had to change 'app/@modal/(.)photos/[id]/page.js' as follows:

    Failing:

    import Frame from '@/components/frame/Frame';
    import Modal from "@/components/modal/Modal";
    

    Successful:

    import Frame from '../../../../components/frame/Frame'
    import Modal from "../../../../components/modal/Modal";
    

Please note that I am using Javascript ('.js') rather than Typescript ('.ts').

Now that I have the nextgram example working with v13.4.7, I'll update to v13.5.4 and see if I can make it work.

If that succeeds, then I'll try adding back the MaterialUI code (MaterialUI is the point of the exercise for me).

I note the dependency on '@headlessui/react' -- that may explain a lot.

@SomervilleTom
Copy link

I updated to v13.5.4 and all is still well (running the 'nextgram' example).

I removed the "experimental" section from 'next.config.js'.

Now I'll try adding back in the MUI behavior (piece by piece).

@joefitter
Copy link

Hey, pretty sure this bug has been fixed but not included in a major release yet. I updated to 13.5.4-canary.6 which fixed the MUI issues

@SomervilleTom
Copy link

SomervilleTom commented Oct 11, 2023

I was finally able to apply a patch to "start-server.js" for v13.5.4 so that 'yarn dev' starts a dev server listening on https instead of http, using the nextgram example code. This is needed because the rest of my environment needs the front end running https instead of http, and because it needs to use the same certs as the rest of the platform (rather than any special-snowflake self-signed certs).

No console complaints, and the MUI version of 'nextgram' behaves as expected.

I'm finally able to resume development on my own MUI modal behavior.

NOTE: I'm pretty sure that adding "@headlessui/react": "^1.7.15" to 'package.json' was a crucial step missing from my first go-round.

@feedthejim
Copy link
Contributor

feedthejim commented Oct 12, 2023

I'm gonna close this issue because it seems while it's clear people are having various issues with parallel routes, it's unclear to me if they are not related to the original issue in particular.

Please open new issues with repros and a description of what doesn't work, and feel free to ping me directly there, I promise to take a look.

@github-actions
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. locked
Projects
None yet
Development

No branches or pull requests