Commit 7b7cee3
authored
Error when app pages do not match any route (#97401)
## What?
This reports an error under `experimental.strictRouteMatching` when a
`page.tsx` is left out of every retained matcher. A page can lose its
own broad catchall matcher and still be valid if it participates in a
more specific matcher, so this checks the final matcher set instead of
treating every pruned candidate as an error.
Both Webpack and Turbopack report every unmatched page in development
and production builds.
## Why?
Pages that are never selected by any complete loader tree are
unreachable by construction. This usually means parallel slots define
incompatible paths without matching pages or defaults, and silently
ignoring those files makes the project look like it has routes that
cannot actually exist.
For example:
```text
app/disagreeing-slots/
├── layout.tsx
├── @first/foo/page.tsx
├── @second/bar/page.tsx
└── [...slug]/page.tsx
```
Every candidate is incomplete: `/foo` has no match in `@second`, `/bar`
has no match in `@first`, and URLs handled only by the catchall have no
matching page or applicable default in either named slot. Strict route
matching prunes all three matchers, and this change reports all three
page files instead of silently leaving them out of the build.
The same validation catches a real `children` branch that only becomes
incomplete below its page:
```text
app/declared-children/
├── layout.tsx
├── page.tsx
└── @panel/
├── default.tsx
└── details/page.tsx
```
`/declared-children` is valid, but `/declared-children/details` only has
a page in `@panel`. Because the declared `children` slot has no matching
page or default at `/details`, that matcher is pruned and
`@panel/details/page.tsx` is reported as unreachable. The root
`page.tsx` is still part of the valid `/declared-children` matcher and
is not reported.
A pruned matcher is not automatically an error. If
`@slot/[...parts]/page.tsx` is combined into retained `/foo` and `/bar`
matchers, that page still participates in routes and remains valid.
## How?
Webpack snapshots the authored app page paths before pruning and
compares them with the pages used by the retained app paths. Turbopack
collects authored page source files from the directory tree and compares
them with the files referenced by the final accepted loader trees. The
tests cover disagreeing named slots, declared `children`, optional
catchalls, route groups, nested slots, and the valid case where a pruned
catchall is still used by more specific matchers.
## Verification
- `pnpm test-start-turbo
test/e2e/app-dir/unmatched-app-pages/unmatched-app-pages.test.ts`
- `pnpm test-start-webpack
test/e2e/app-dir/unmatched-app-pages/unmatched-app-pages.test.ts`
- `pnpm test-dev-turbo
test/e2e/app-dir/unmatched-app-pages/unmatched-app-pages.test.ts`
- `pnpm test-dev-webpack
test/e2e/app-dir/unmatched-app-pages/unmatched-app-pages.test.ts`
- `pnpm test-start-turbo
test/e2e/app-dir/parallel-routes-pruned-matchers/parallel-routes-pruned-matchers.test.ts`
- `pnpm test-start-webpack
test/e2e/app-dir/parallel-routes-pruned-matchers/parallel-routes-pruned-matchers.test.ts`
<!-- NEXT_JS_LLM -->1 parent ec62d6a commit 7b7cee3
62 files changed
Lines changed: 621 additions & 106 deletions
File tree
- crates/next-core/src
- packages/next/src
- build
- server/lib/router-utils
- test/e2e/app-dir
- explicit-parallel-route-children-detection
- app/nested
- @sidebar/incomplete
- instant-validation
- app/suspense-in-root/static
- config-depth-preference
- @slot/[...catchall]
- deeper/@anotherSlot
- cross-slot-blocking/inner/@panel
- interception-dynamic-segment/app/named-host/@canonical/named-catchall-target/[...slug]
- parallel-routes-and-interception/app/parallel
- parallel-routes-catchall-slotted-non-catchalls/app/[locale]/other
- parallel-routes-not-found/app
- parallel-routes-pruned-matchers
- app
- (pruning-group)/grouped/[...slug]
- children-catchall
- @first/foo
- @second/bar
- [...slug]
- nested-parallel
- @outer/[...slug]
- [...slug]
- optional-children-catchall
- [[...slug]]
- unmatched-app-pages
- app
- (pruning-group)/grouped
- @slot/specific
- [...slug]
- specific
- declared-children
- @panel
- details
- disagreeing-slots
- @first/foo
- @second/bar
- [...slug]
- interception-host
- @canonical
- intercepted/[...slug]
- @modal
- (.)intercepted/[...slug]
- @secondary
- nested-parallel
- @outer
- @inner/specific
- [...slug]
- specific
- [...slug]
- specific
- optional-catchall
- @slot/specific
- [[...slug]]
- specific
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
486 | 486 | | |
487 | 487 | | |
488 | 488 | | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
489 | 499 | | |
490 | 500 | | |
491 | 501 | | |
| |||
613 | 623 | | |
614 | 624 | | |
615 | 625 | | |
| 626 | + | |
616 | 627 | | |
617 | 628 | | |
618 | 629 | | |
| |||
709 | 720 | | |
710 | 721 | | |
711 | 722 | | |
| 723 | + | |
712 | 724 | | |
713 | 725 | | |
714 | 726 | | |
| |||
717 | 729 | | |
718 | 730 | | |
719 | 731 | | |
| 732 | + | |
720 | 733 | | |
721 | 734 | | |
722 | 735 | | |
| |||
742 | 755 | | |
743 | 756 | | |
744 | 757 | | |
| 758 | + | |
745 | 759 | | |
746 | 760 | | |
747 | 761 | | |
| |||
750 | 764 | | |
751 | 765 | | |
752 | 766 | | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
753 | 772 | | |
754 | 773 | | |
755 | 774 | | |
| |||
972 | 991 | | |
973 | 992 | | |
974 | 993 | | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
975 | 1021 | | |
976 | 1022 | | |
977 | 1023 | | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
978 | 1086 | | |
979 | 1087 | | |
980 | 1088 | | |
| |||
1852 | 1960 | | |
1853 | 1961 | | |
1854 | 1962 | | |
| 1963 | + | |
| 1964 | + | |
| 1965 | + | |
| 1966 | + | |
| 1967 | + | |
| 1968 | + | |
1855 | 1969 | | |
1856 | 1970 | | |
1857 | 1971 | | |
1858 | 1972 | | |
1859 | | - | |
| 1973 | + | |
| 1974 | + | |
1860 | 1975 | | |
1861 | 1976 | | |
1862 | 1977 | | |
| |||
2052 | 2167 | | |
2053 | 2168 | | |
2054 | 2169 | | |
| 2170 | + | |
2055 | 2171 | | |
2056 | 2172 | | |
2057 | 2173 | | |
| |||
2100 | 2216 | | |
2101 | 2217 | | |
2102 | 2218 | | |
| 2219 | + | |
2103 | 2220 | | |
2104 | 2221 | | |
2105 | 2222 | | |
| |||
2178 | 2295 | | |
2179 | 2296 | | |
2180 | 2297 | | |
| 2298 | + | |
2181 | 2299 | | |
2182 | 2300 | | |
2183 | 2301 | | |
2184 | 2302 | | |
2185 | 2303 | | |
2186 | 2304 | | |
| 2305 | + | |
| 2306 | + | |
| 2307 | + | |
| 2308 | + | |
| 2309 | + | |
| 2310 | + | |
| 2311 | + | |
| 2312 | + | |
2187 | 2313 | | |
2188 | 2314 | | |
2189 | 2315 | | |
2190 | 2316 | | |
2191 | | - | |
2192 | | - | |
| 2317 | + | |
| 2318 | + | |
2193 | 2319 | | |
2194 | 2320 | | |
2195 | 2321 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
| |||
409 | 410 | | |
410 | 411 | | |
411 | 412 | | |
| 413 | + | |
412 | 414 | | |
413 | 415 | | |
414 | 416 | | |
415 | 417 | | |
416 | 418 | | |
417 | 419 | | |
418 | | - | |
419 | | - | |
420 | | - | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
421 | 424 | | |
| 425 | + | |
| 426 | + | |
422 | 427 | | |
423 | 428 | | |
424 | 429 | | |
425 | | - | |
| 430 | + | |
426 | 431 | | |
427 | 432 | | |
428 | 433 | | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
429 | 452 | | |
430 | 453 | | |
431 | 454 | | |
| |||
Lines changed: 45 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
224 | 236 | | |
225 | 237 | | |
226 | 238 | | |
| |||
299 | 311 | | |
300 | 312 | | |
301 | 313 | | |
302 | | - | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
303 | 317 | | |
304 | 318 | | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
305 | 324 | | |
306 | 325 | | |
307 | 326 | | |
| |||
310 | 329 | | |
311 | 330 | | |
312 | 331 | | |
313 | | - | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
314 | 335 | | |
315 | 336 | | |
316 | 337 | | |
317 | 338 | | |
| 339 | + | |
318 | 340 | | |
319 | 341 | | |
320 | 342 | | |
| |||
502 | 524 | | |
503 | 525 | | |
504 | 526 | | |
505 | | - | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
506 | 530 | | |
507 | 531 | | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
508 | 550 | | |
509 | 551 | | |
510 | 552 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
0 commit comments