Next.js Discord

Discord Forum

Nextjs returns 404 error on existing route

Answered
Sloth bear posted this in #help-forum
Open in Discord
Avatar
Sloth bearOP
When i try to deploy parallel routes with nested routes, it returns a 404 error when i try to access nested route with a hard refresh, with a soft refresh it does not gives errors it returns the nested route.

i have made an issue about this since two days, but i didn't get any solution. this is the link https://github.com/vercel/next.js/issues/59219

is possible to make parallel routes with nested routes right?
Answered by Siberian Flycatcher
In the updated repo, your Header that awaits a promise is still a server component (even though it renders a client component).

import ClientHeader from "@/components/Header";

// This is a server component
const Header = async () => {
  const username = "user01"; // getting data from server
  await new Promise((r) => setTimeout(r, 10000));

  return <ClientHeader username={username} />;
};

export default Header;


And you can still render this server component in your Root Layout and wrap it with Suspense (no need for parallel routes).

/app/layout.tsx
import Header from './Header'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Suspense fallback="Loading...">
          <Header />
        </Suspense>
        {children}
      </body>
    </html>
  );
}


i'm just wondering why it throws 404 error when access nested routes.

Because you didn't provide default.js. The parallel route needs to specify default.js for cases when you visit a subroute that isn't available in your parallel route.

Check out the example here https://twitter.com/asidorenko_/status/1732846254420308362
View full answer

16 Replies

Avatar
Siberian Flycatcher
Hi 👋

You can rename app/@header/page.tsx into app/@header/default.tsx.
This will render the header for all routes.

However, there are more straightforward ways to render a header than using parallel routes. Is there anything stopping you from rendering your header inside the root layout?

If you don't want async action inside the header to block the rendering of your page, you can wrap the Header with Suspense.

/app/layout.tsx
import Header from './Header'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Suspense fallback="Loading...">
          <Header />
        </Suspense>
        {children}
      </body>
    </html>
  );
}
Avatar
Sloth bearOP
If the header is a client component it not possible to put it in a Suspense component...

I tried to rename the app/@header/page.tsx to app/@header/default.tsx, I made a fake promise that wait 10s before return the jsx content.

const Header = async () => {
  await new Promise((r) => setTimeout(r, 10000));

  
  return <header>header</header>;
};

export default Header;


But changing the name from page.tsx to default.tsx does not render this parallel any more. in fact if i reload the page it loads for 10s before rendering anything.

I'm having a header client-component that get the session to provide some user data, i'm next-auth session, when i use the useSession hook it takes a lot of time to load the session rather then get it from the server-side. so to reduce time i decided to put the header in a parallel route, that waits to get the session and then pass it to the header component. seeing that is a parallel route, the reset of the content can be displayed while the header route loads.

i can achieve the same result by using two header components, serverHeader.tsx an async component that wait the promise and pass it to clientHeader.tsx and then put the serverHeader.tsx in a Suspense.

I think that using parallel route will be cleaner cause i just have one Header component. the occurs when having parallel and nested routes at the same level, cause when attempting to access nested routes i throw a 404 error.

Does this means that is not possible to use parallel routes with nested ones?
Avatar
Sloth bearOP
can i use parallel routes with nested routes?
Avatar
Siberian Flycatcher
But changing the name from page.tsx to default.tsx does not render this parallel any more. in fact if i reload the page it loads for 10s before rendering anything.

That's because you await a promise for 10 seconds in your Header server component. The default.js won't pick up a loading.js as a Suspense boundary. You will need to provide the Suspense boundary manually.

// app/@header/default.tsx
const Header = async () => {
  await new Promise((r) => setTimeout(r, 10000));
  return <header>header</header>;
};

export default function Page() {
  return (
    <Suspense fallback="Loading...">
      <Header />
    </Suspense>
  )
};


However, I don't think you need a parallel route for your use case.

- If your Header is a server component (like in your test right now), then you can render it inside the root layout and wrap it with Suspense so that the rest of your page can render while the Header is loading.
- If your Header is a client component, it will not block page rendering, so you will not have this problem in the first place.
Avatar
Sloth bearOP
i had just updated the test repo, with the example that i'm trying to explain...

the code you provided will work when the header is a server component but my header is a client component (i updated it on the test) so i can't put it in Suspense. but this header client component need to receaved some date from server side to be loaded.

i think to make some thing like this
import HeaderClient from "@/components/Header";

export default async function HeaderServer() {
  const username = "user01";
  await new Promise((r) => setTimeout(r, 10000));
  return <HeaderClient username={username} />;
}


I think that using parallel route will be cleaner cause i just have one Header component.

i'm just wondering why it throws 404 error when access nested routes.
Avatar
Siberian Flycatcher
In the updated repo, your Header that awaits a promise is still a server component (even though it renders a client component).

import ClientHeader from "@/components/Header";

// This is a server component
const Header = async () => {
  const username = "user01"; // getting data from server
  await new Promise((r) => setTimeout(r, 10000));

  return <ClientHeader username={username} />;
};

export default Header;


And you can still render this server component in your Root Layout and wrap it with Suspense (no need for parallel routes).

/app/layout.tsx
import Header from './Header'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Suspense fallback="Loading...">
          <Header />
        </Suspense>
        {children}
      </body>
    </html>
  );
}


i'm just wondering why it throws 404 error when access nested routes.

Because you didn't provide default.js. The parallel route needs to specify default.js for cases when you visit a subroute that isn't available in your parallel route.

Check out the example here https://twitter.com/asidorenko_/status/1732846254420308362
Answer
Avatar
Alfonsus Ardani
have you tried deleting the next folder? in my experience parallel routes tend to be a bit sticky
Avatar
Sloth bearOP
yes but the problem persists
Avatar
Sloth bearOP
Thanks for helping 🙏
Avatar
Alfonsus Ardani
does that message solves your issue?
Avatar
Sloth bearOP
yes i had also created an issue in github about this
https://github.com/vercel/next.js/issues/59219

thanks for your time
Avatar
Alfonsus Ardani
So which one eventually solves your issue? Is it solved via the github issue link?
Avatar
Sloth bearOP
the issue i created was before opening a help-forum but i solved here
Avatar
Alfonsus Ardani
so did alex's message solved your issue?
Avatar
Sloth bearOP
yes
Avatar
Alfonsus Ardani
perfect! thanks, im glad your issue is solved ^^