[🐞] v2: route matcher doesn't backtrack — a static route prefix 404s deeper dynamic routes; no specificity ranking across groups
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 22.1k
- Forks
- 1.4k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 52
Description
Which component is affected?
Qwik Router
Describe the bug
In @qwik.dev/router 2.0.0-beta.38 the route matcher commits to the first child match per path segment and never backtracks. Two symptoms, both regressions from Qwik 1 (qwik-city 1.19), reproducible in dev AND production preview builds:
-
A static route shadows deeper dynamic routes sharing its prefix. With
(marketing)/pricing/index.tsxand(pages)/[section]/[topic]/[article]/index.tsx, requesting/pricing/guides/introreturns 404 — the matcher locks onto the staticpricingnode, dead-ends, and never tries the dynamic family./docs/guides/intro(no static prefix) works, proving the dynamic route is registered correctly. -
No specificity ranking when multiple route families fully match. With
(rss)/[section]/feed.xml/index.tsx, requesting/alpha/feed.xmlrenders the[section]/[topic]page (both segments dynamic) instead of the feed route (dynamic + static) — group iteration order decides, not route specificity.
Cause (from reading the shipped code)
In lib/chunks/head.qwik.mjs, findChild returns the first hit (exact static child → groups in order → wildcard) and matchRouteTree walks segments in a single forward loop with no candidate stack; a dead end sets matched=false and breaks. The only fallback is the [...rest] restFallback. There is no cross-candidate comparison, so full-match ties resolve by group order.
Additional information
In Qwik 1 both URL families coexist by design (ordered route matching). This blocks migrating any v1 app whose URL space mixes static marketing pages with a dynamic catalog under the same prefixes.
We're carrying a local patch that makes matching backtracking + ranks completed candidates lexicographically by segment kind (static < wildcard < catch-all), which restores v1 behavior and passes our full e2e suite — happy to turn it into a PR.
Reproduction
https://github.com/blakeley/router-matcher-no-backtracking
Steps to reproduce
bun install && bun run devcurl -sL localhost:5173/pricing→ 200 STATIC-PAGEcurl -sL localhost:5173/pricing/guides/intro→ 404 (expected 200 ARTICLE)curl -sL localhost:5173/docs/guides/intro→ 200 ARTICLE (control)curl -sL localhost:5173/alpha/feed.xml→ 200 TOPIC alpha/feed.xml (expected FEED alpha)
Same results with build + preview.
Note (documented in the repro README): the repro depends on route-group sort order — the static page's group must sort before the dynamic family's group.
System Info
@qwik.dev/core 2.0.0-beta.38
@qwik.dev/router 2.0.0-beta.38
vite 6
bun 1.2.17
Node 22
macOS (darwin arm64)
Additional Information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read lib/chunks/head.qwik.mjs, especially findChild and matchRouteTree, then run the linked reproduction with bun install && bun run dev. Verify the matcher handles both the deeper dynamic route and the more specific feed route in development and preview builds, with the documented 200 responses instead of the 404 or less-specific page.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100