Migrating custom routes from v2 to v3 I have a handful of custom routes configured on this project like

'action/(?P&lt;custom_id&gt;[a-zA-Z][0-9]{6})/(?P&lt;slug&gt;.*)' =&gt; 'action/_member',

If I'm reading the docs correctly, then those need to change to become

'action/&lt;custom_id:[a-zA-Z][0-9]{6}&gt;/&lt;entrySlug:{slug}.*&gt;' =&gt; [
        'template' =&gt; 'action/_member'
    ],


but that gives me a template not found error when I hit localhost/action/L100582/&amp;session=115

If I simplify the rule to become

action/steven' =&gt; [ 'template' =&gt; 'action/_member' ]

and hit, localhost/action/steven the template loads just fine.

I can't wrap my little head around what I'm missing.
The {slug} token you’re using there is going to get replaced with Craft’s slug pattern:

(?:[\p{L}\p{N}\p{M}\.\_\-]+)


Since that’s not an optional pattern, the resulting regex isn’t going to match your example URL, which doesn’t have a slug after the custom_id.

I’d recommend you use two separate routes that both point to the same template:

'action/&lt;custom_id:[a-zA-Z][0-9]{6}&gt;' =&gt; ['template' =&gt; 'action/_member'],
'action/&lt;custom_id:[a-zA-Z][0-9]{6}&gt;/&lt;entrySlug:{slug}&gt;' =&gt; ['template' =&gt; 'action/_member'],


(And just in case it wasn’t intentional, worth pointing out that the slug is going to be called entrySlug as opposed to slug with that route, which is another change from your Craft 2 route. Use &lt;slug:{slug}&gt; if you didn’t mean to change the name.)