Routers disagree on a param segment containing a second `:`
Author: harshit-d3vCreated Sep 12, 2026Updated Sep 16, 2026
Register /date/:year-:month and request /date/2026-09. Each router does something different.
| Router | Result |
|---|---|
| RegExpRouter | matches, param year-:month = "2026-09" |
| TrieRouter | matches, param year-:month = "2026-09" |
| LinearRouter | matches, param year = "2026-09" |
| PatternRouter | no match (404) |
The routers are meant to be interchangeable. SmartRouter picks one at runtime and hono/tiny ships PatternRouter, so the same app returns a param, a differently named param, or a 404 depending on which one is active.
Reproduction
import { RegExpRouter } from 'hono/router/reg-exp-router'
import { TrieRouter } from 'hono/router/trie-router'
import { PatternRouter } from 'hono/router/pattern-router'
import { LinearRouter } from 'hono/router/linear-router'
for (const [name, R] of [
['RegExpRouter', RegExpRouter],
['TrieRouter', TrieRouter],
['PatternRouter', PatternRouter],
['LinearRouter', LinearRouter],
] as const) {
const r = new R()
r.add('GET', '/date/:year-:month', 'h')
console.log(name, JSON.stringify(r.match('GET', '/date/2026-09')))
}RegExpRouter [[["h",{"year-:month":1}]],["/date/2026-09","2026-09",""]]
TrieRouter [[["h",{"year-:month":"2026-09"}]]]
PatternRouter [[]]
LinearRouter [[["h",{"year":"2026-09"}]]]ParamKeys<'/date/:year-:month'> is 'year-:month', which matches RegExpRouter and TrieRouter. common.case.test.ts has no case for this, so nothing catches the difference.
Which behaviour is correct? If it's the one the types describe, I'll align LinearRouter and PatternRouter and add the case to the shared suite.
Source: honojs/hono