Skip to content

fix(qwik-router): match routes that continue after a [...rest] segment - #9198

Merged
wmertens merged 1 commit into
QwikDev:mainfrom
tzdesign:fix/router-rest-param-followed-by-segments
Oct 12, 2026
Merged

wmertens merged 1 commit into
QwikDev:mainfrom
tzdesign:fix/router-rest-param-followed-by-segments

Conversation

@tzdesign

Copy link
Copy Markdown
Contributor

What is it?

  • Bug

Description

Routes that continue after a [...rest] segment are unreachable in the v2 router. With

src/routes/[...path]/index.tsx
src/routes/[...path]/product/[id]/index.tsx

/sports/balls/product/123 always resolves to [...path]/index.tsx with path: 'sports/balls/product/123'. Qwik City 1 matched the second route with path: 'sports/balls', id: '123'. We hit this while migrating a shop from Qwik City 1.19 to 2.0.0-rc.2, where every product URL lives below a category catch-all.

The cause is in packages/qwik-router/src/runtime/src/routing.ts: matchRestNode always consumes all remaining segments with done: true, and findMatchChain then ends the chain in matchRestTail, so the children of a rest node are never tried. The backtracking from #8899 keeps this behaviour.

The fix:

  • When a rest node has route segments below it, findChildAll also yields partial rest matches that leave segments for its children, from the longest rest down to an empty one (/product/123 gives path: '', as in v1). Rest nodes without children are unchanged.
  • Partial matches keep the Rest kind, so static and [param] matches still outrank them, and they come before the full rest so the deeper route wins when both reach a page.
  • ChildMatch gets an optional span, and matchRouteTree walks the chain by its own index while advancing i by the consumed segments.
  • findMatchChain returns early when the rival tail is empty. This could not happen before, but with variable spans it would otherwise read bound[0] of an empty bound.

Children below a rest node were unreachable before, so existing route trees match exactly as they did.

Checklist

  • My code follows the developer guidelines of this project
  • I performed a self-review of my own code
  • I added a changeset with pnpm change
  • I added new tests to cover the fix / functionality

Tests: 7 new cases in routing.unit.ts (4 of them fail on main), all 801 qwik-router unit tests pass, and typecheck, eslint and prettier are clean.

The route trie ended every match at a `[...rest]` node: the rest always
consumed all remaining segments, so routes below it such as
`[...path]/product/[id]` were unreachable and every URL fell through to
`[...path]`. Qwik City 1 matched these routes.

A rest node with route segments below it now also yields partial
matches that leave segments for its children, from the longest rest down
to an empty one (`/product/1` gives `path: ''`). They rank below static
and `[param]` matches like any rest match, and before the full rest, so
the deeper route wins when both apply. The match walk advances by the
segments each chain entry consumed instead of by chain index.
@tzdesign
tzdesign requested a review from a team as a code owner October 12, 2026 10:00
@changeset-bot

changeset-bot Bot commented Oct 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 735ed65

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@qwik.dev/router Patch
eslint-plugin-qwik Patch
@qwik.dev/mcp Patch
create-qwik Patch
@qwik.dev/devtools Patch
@qwik.dev/react Patch
@qwik.dev/utils Patch
@qwik.dev/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Oct 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

@qwik.dev/core

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/core@9198

@qwik.dev/router

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/router@9198

@qwik.dev/utils

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/utils@9198

eslint-plugin-qwik

npm i https://pkg.pr.new/QwikDev/qwik/eslint-plugin-qwik@9198

create-qwik

npm i https://pkg.pr.new/QwikDev/qwik/create-qwik@9198

@qwik.dev/optimizer

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/optimizer@9198

@qwik.dev/devtools

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/devtools@9198

@qwik.dev/mcp

npm i https://pkg.pr.new/QwikDev/qwik/@qwik.dev/mcp@9198

commit: 735ed65

@wmertens wmertens left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wmertens
wmertens merged commit 2ee8809 into QwikDev:main Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants