[labs/router] getTailGroup selects the wrong tail: unanchored digit regex and lexicographic group ordering
Which package(s) are affected?
@lit-labs/router
Description
getTailGroup in packages/labs/router/src/routes.ts picks the wrong wildcard tail in two cases:
- Named params containing a digit hijack the tail. For a route like
/user/:id1/*matching/user/42/rest/path,URLPatternproduces groups{"0": "rest/path", "id1": "42"}. The check/\d+/.test(key)is unanchored, soid1qualifies as a tail candidate, and the child route receives"42"instead of"rest/path". - Numeric group ordering is lexicographic. With 10+ numeric groups,
key > tailKeycompares strings, so group"9"wins over"10"and the tail is off by one.
Both bugs live in a single condition: https://github.com/lit/lit/blob/main/packages/labs/router/src/routes.ts#L295-L303
Reproduction
Node 18+ (native URLPattern):
const g1 = new URLPattern({pathname: '/user/:id1/*'}).exec({pathname: '/user/42/rest/path'}).pathname.groups;
// -> {"0": "rest/path", "id1": "42"}
const g2 = new URLPattern({pathname: '/*/*/*/*/*/*/*/*/*/*/*'}).exec({pathname: '/a/b/c/d/e/f/g/h/i/j/k'}).pathname.groups;
const current = (groups) => { let t; for (const k of Object.keys(groups)) { if (/\d+/.test(k) && (t === undefined || k > t)) t = k; } return t && groups[t]; };
current(g1); // -> "42", expected "rest/path"
current(g2); // -> "j", expected "k"
Through the public API: a parent route /user/:id1/* with a child route :a/:b throws No route found on goto('/user/42/rest/path') because the child receives "42" instead of "rest/path".
Workaround
Avoid digits in named param names when combined with a trailing wildcard, and avoid patterns producing 10+ numeric groups.
Is this a regression?
No. Present since the initial implementation (#2331); the function has not changed since.
Affected versions
@lit-labs/router 0.1.4 (current main)
Browser/OS/Node environment
All (logic bug, verified on Node 24 + native URLPattern).
Proposed fix
Anchor the regex (/^\d+$/) and compare group keys numerically. Regression tests via nested routes. Happy to send a PR.
Source: lit/lit