#8893·qwik

[] v2: route matcher doesn't backtrack — a static route prefix 404s deeper dynamic routes; no specificity ranking across groups

Author: blakeleyCreated Jul 31, 2026Updated Jul 31, 2026

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:

  1. A static route shadows deeper dynamic routes sharing its prefix. With (marketing)/pricing/index.tsx and (pages)/[section]/[topic]/[article]/index.tsx, requesting /pricing/guides/intro returns 404 — the matcher locks onto the static pricing node, dead-ends, and never tries the dynamic family. /docs/guides/intro (no static prefix) works, proving the dynamic route is registered correctly.

  2. No specificity ranking when multiple route families fully match. With (rss)/[section]/feed.xml/index.tsx, requesting /alpha/feed.xml renders 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

  1. bun install && bun run dev
  2. curl -sL localhost:5173/pricing → 200 STATIC-PAGE
  3. curl -sL localhost:5173/pricing/guides/intro → 404 (expected 200 ARTICLE)
  4. curl -sL localhost:5173/docs/guides/intro → 200 ARTICLE (control)
  5. 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