QwikDev / QwikDev/qwik

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

Open
#8,893 0 comments 0 reactions 0 assignees View on GitHub

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:

  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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.