A Next.js App Router dashboard has app/dashboard/layout.tsx with a @team slot. Navigating to /dashboard/settings by clicking a link inside the app works, but opening or reloading that same URL directly returns a 404. What causes this, and how do you fix it?
answer
- works until someone presses reload
- soft navigation remembers, hard load cannot
- the slot has no matching route
- every slot needs a fallback file
- default.tsx, often returning null
basics
~20 sThe @team slot has no route matching /dashboard/settings. On a client navigation Next keeps showing the slot's previous content, but on a full page load there is no previous state, so it falls back to the slot's default.tsx — and with no default.tsx it renders a 404. Add app/dashboard/@team/default.tsx.
solid answer
~50 sEvery parallel route slot resolves its own route for the current URL, and `@team` has nothing matching `settings`. The two navigation paths then behave differently. On a soft, client-side navigation Next already knows what `@team` was showing and keeps rendering that, so the page looks fine. On a hard load — a refresh, or pasting the URL into a new tab — there is no prior state to preserve, so Next looks for `default.tsx` in the unmatched slot; if the file does not exist it cannot render that slot at all and 404s the route. The fix is to add `app/dashboard/@team/default.tsx` returning whatever the slot should show when it has no match, often just `null` or a placeholder card. Alternatively, give `@team` a real `settings` route. The rule of thumb: any slot that will not match every URL under its layout needs a `default.tsx`, and `children` follows the same rule.
go deeper
Remember the file name: an @ slot that will not match every URL under its layout needs a default.tsx beside it, and returning null from that file is a normal answer.
Explain the asymmetry — the router keeps each slot's previous sub-route across a client navigation, but a hard load has no previous state and must fall back to default.tsx or fail the route.
Diagnose it from the symptom: a page that works while clicking and 404s on refresh points at an unmatched slot. Say how you would find it — enumerate the URLs each slot must cover and hard-load them — and reject the not-found.tsx and caching explanations.
Make it a systemic non-issue: a review rule pairing every new slot with its default.tsx, and a smoke check that hard-loads routes rather than only clicking through, so navigation-dependent breakage never reaches production.
## Why the two navigations differ Parallel routes make the router track more than one active route at a time. For a layout with `children` and `@team`, the router holds an active sub-route for *each* slot. When you navigate on the client from `/dashboard` to `/dashboard/settings`, the router updates the slots that have a match and, for slots that do not, keeps the sub-route they were already showing. That is deliberate: it is what lets a dashboard panel stay put while the main area navigates. A hard load has no such history. Opening `/dashboard/settings` in a fresh tab, or pressing reload, gives the server nothing but the URL. It resolves every slot from scratch, and for `@team` there is no route to resolve. At that point Next needs a fallback, and the fallback is a file: `default.tsx` in the slot's folder. ## What default.tsx is `default.tsx` exports a component that Next renders for a slot when the current URL has no matching route inside that slot and there is no remembered state to fall back on. It is not an error page and not a 404 page — it is the slot's "nothing to show here" rendering. ```tsx // app/dashboard/@team/default.tsx export default function Default() { return null } ``` Returning `null` is completely normal: it means the layout renders that region empty. When the region has a natural resting state — an empty card, a prompt to select something — put that in `default.tsx` instead. ## What happens without it With no `default.tsx` and no match, Next has an unresolvable slot and renders a 404 for the route. The nasty part is the asymmetry: the app works while you click around in development, and breaks the first time anyone refreshes, deep-links, or hits the page from a search result. Bug reports arrive as "works for me" because the reporter and the developer navigated differently. That asymmetry is the whole reason this question is asked. ## The fixes, in order of preference 1. **Add `default.tsx` to the unmatched slot.** The right answer in almost every case, and the one interviewers are listening for. 2. **Give the slot a real matching route** — `app/dashboard/@team/settings/page.tsx` — when the slot genuinely has something to show at that URL. 3. **Restructure**, if the slot should not have been a slot at all. A panel that always shows the same thing regardless of URL is a component, not a parallel route. ## `children` plays by the same rules Because `children` is just the unnamed slot, it can also be the unmatched one, and `app/dashboard/default.tsx` is its fallback. This comes up with modals: when a `@modal` slot has a route for a URL but the main tree does not, the *main* slot is the one needing the fallback. ## How to catch this before users do - For each slot, enumerate the URLs its layout can be active for, and ask which of them the slot does not match. If any, that slot needs `default.tsx`. - Test parallel-route pages by hard-loading them, not only by clicking through. A refresh on every route touched by a slot is the cheap manual check. - Treat "add the slot folder" and "add its `default.tsx`" as one step in code review; the file is boilerplate, and its absence is invisible until a hard load. ## The common wrong diagnoses - **"Add a `not-found.tsx`."** That changes what the 404 *looks* like; the route still fails. - **"Add a `page.tsx` at the slot root."** That gives the slot a match for the layout's own base URL only, so the refresh on `/dashboard/settings` still fails. - **"It is a caching problem."** Nothing about this is cached — it is route resolution, and it reproduces on a cold server every time.
- Why does Next preserve the slot's previous sub-route on a client navigation instead of clearing it?Because that is the point of parallel routes: each slot has its own active sub-route, so navigating the main area should not reset a panel beside it. Preservation only works when there is state to preserve, which is exactly why the behaviour diverges on a hard load and why `default.tsx` exists.
- Does the children slot ever need a default.tsx?Yes. `children` is the unnamed slot and follows identical rules, so `app/dashboard/default.tsx` is its fallback. It matters most with modals: if a `@modal` slot matches a URL that the main tree does not, `children` is the unmatched slot and it needs the fallback.
- Would adding a not-found.tsx to the dashboard segment fix this?No. `not-found.tsx` only changes what a 404 renders; it does not make the unmatched slot resolvable, so the route still fails. The 404 here is a symptom of an unresolvable slot, not of a missing page, and only `default.tsx` or a real matching route addresses it.
default.tsx is a slot's understudy: when the URL hands the slot no scene to play, the understudy walks on. Without one, the whole show — not just that role — is cancelled.
saying these in an interview costs you the question
- Blames a missing page.tsx instead of default.tsx
- Assumes soft and hard navigation resolve slots identically
- Calls default.tsx the slot's 404 page
- Says not-found.tsx fixes an unmatched slot
- Dismisses it as a caching or build artefact