You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
There was some code added in the catch-all route normalization that doesn't seem to make sense -- it was checking if the provided appPath depth was larger than the catch-all route depth, prior to inserting it. But it was comparing depths in an inconsistent way (.length vs .length - 1), and the catch all path was also considering the @slot and /page suffix as part of the path depth.
This means that if you had a @modal/[...catchAll] slot, it wouldn't be considered for a page like /foo/bar/baz, because /foo/bar/baz (depth: 4 with the current logic) and /@modal/[...catchAll]/page (depth: 3 with the current logic) signaled that the /foo/bar/baz route was "more specific" and shouldn't match the catch-all.
I think this was most likely added to resolve a bug where we were inserting optional catch-all ([[...catchAll]]) routes into parallel slots. However, optional catch-all routes are currently unsupported with parallel routes, so this feature didn't work properly and the partial support introduced a bug for regular catch-all routes.
How
This removes the confusing workaround and skips optional catch-all segments in this handling. Separately, we can add support for optional catch-all parallel routes, but doing so will require quite a bit more changes & also similar handling in Turbopack. Namely, if have a top-level optional catch-all, in both the Turbopack & current Webpack implementation, that top-level catch-all wouldn't be matched. And if you tried to have an optional catch-all slot, in both implementations, the app would error with:
You cannot define a route with the same specificity as a optional catch-all route ("/" and "/[[...catchAll]]")
because our route normalization logic does not treat slots specificity differently than pages.
Note: This keeps the test that was added when this logic was first introduced in #60776 to ensure that the case this was originally added for still passes.
I don't know if these changes are related, but I still get the following error
[Error: Invalid segment Parallel("controls"), catch all segment must be the last segment (segments: [Dynamic("lang"), Dynamic("city"), Static("clinics"), OptionalCatchAll("args")])
Debug info:
Execution of get_entrypoints_with_issues failed
Execution of Project::entrypoints failed
Execution of AppProject::routes failed
Execution of directory_tree_to_entrypoints_internal failed
Execution of directory_tree_to_entrypoints_internal failed
Execution of directory_tree_to_entrypoints_internal failed
Execution of directory_tree_to_entrypoints_internal failed
Execution of directory_tree_to_entrypoints_internal failed
Execution of directory_tree_to_loader_tree failed
Invalid segment Parallel("controls"), catch all segment must be the last segment (segments: [Dynamic("lang"), Dynamic("city"), Static("clinics"), OptionalCatchAll("args")])] {
code: 'GenericFailure'
}
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & Why
There was some code added in the catch-all route normalization that doesn't seem to make sense -- it was checking if the provided
appPath
depth was larger than the catch-all route depth, prior to inserting it. But it was comparing depths in an inconsistent way (.length
vs.length - 1
), and the catch all path was also considering the@slot
and/page
suffix as part of the path depth.This means that if you had a
@modal/[...catchAll]
slot, it wouldn't be considered for a page like/foo/bar/baz
, because/foo/bar/baz
(depth: 4 with the current logic) and/@modal/[...catchAll]/page
(depth: 3 with the current logic) signaled that the/foo/bar/baz
route was "more specific" and shouldn't match the catch-all.I think this was most likely added to resolve a bug where we were inserting optional catch-all (
[[...catchAll]]
) routes into parallel slots. However, optional catch-all routes are currently unsupported with parallel routes, so this feature didn't work properly and the partial support introduced a bug for regular catch-all routes.How
This removes the confusing workaround and skips optional catch-all segments in this handling. Separately, we can add support for optional catch-all parallel routes, but doing so will require quite a bit more changes & also similar handling in Turbopack. Namely, if have a top-level optional catch-all, in both the Turbopack & current Webpack implementation, that top-level catch-all wouldn't be matched. And if you tried to have an optional catch-all slot, in both implementations, the app would error with:
because our route normalization logic does not treat slots specificity differently than pages.
Note: This keeps the test that was added when this logic was first introduced in #60776 to ensure that the case this was originally added for still passes.
Fixes #62948
Closes NEXT-2728