You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Restore Support for app.all('*') Wildcard in Express v5 #6711
This breaks a very common catch-all route pattern used widely in v4 projects.
🔍 Root Cause
1.Express v5 migrated to a stricter version of path-to-regexp.
2.Unnamed wildcards (*) are no longer allowed.
3.Developers must now explicitly name the wildcard parameter.
✅ Expected Behavior
Express v5 should either:
Gracefully support app.all('*') as a valid catch-all syntax (to maintain backward compatibility).
Or, if strict syntax is required:
Provide a clearer error message explaining the new requirement.
Update docs & migration guide to emphasize the change prominently.
📌 Suggested Fixes
Restore legacy * wildcard syntax support (backward compatibility).
Or provide an explicit alternative (e.g. app.all('/*')) documented as the replacement.
Improve error messaging in path-to-regexp.
🔗 Related Issue
This request builds upon Issue #6664 where the problem was first reported. Maintainers clarified that this is not a bug but an intentional change — hence this formal feature request.
Actually, this is how it should be used in this version, the functionality was never removed, it's just that now it needs to be named. Please check the migration guide (https://expressjs.com/en/guide/migrating-5#path-syntax).
What I understand is that they want it to go back to how it was before, without having to name it.
(@bjohansebas )When we use (app.all('*', (req, res) => res.send('Not Found')); ) we get the error:(throw new TypeError(Missing parameter name at ${i}: ${DEBUG_URL}); ). Can we update this? Because the error message does not explain anything clearly. It should be something that, when read, the user can understand what needs to be updated.Basically for beginners.
@Tanmayshi Could you provide an example message of what could help you or someone else understand has broken better? I have a release ready that marginally improves this, but it isn’t a rewrite to the message, so it could still use your input to make it better.
@Tanmayshi , from what I ve gathered from the docs, app.all() should not be used to handle global catch all routers, but app.use() instead. Maybe someone more knowledgeable can provide their insight too
App.all() should be used when any req method should return the same response on any given endpoint - eg:
(@blakeembrey )You could make the message a bit more beginner-friendly so it’s easier to understand. Most beginners use Express, and the current message doesn’t really feel aligned with that perspective.
@Tanmayshi I understand you want it to be beginner friendly, I’m hoping to understand what would have helped you solve this. I hope it’s clear that I tried to make the errors friendly to begin with, and included a URL you could open to read more, in an attempt to make it beginner friendly already but it doesn’t seem to be enough.
Ran into this myself today when updating an old project. I believe this change was a bad idea and can't intuitively see a reason to make *splat a special token; it seems like simply adding * as the special token would have worked just as well; a plain * with nothing preceding it is not a valid regex.
That said, I agree the error messaging needs improvement. The message I saw is:
Uncaught Exception: TypeError: Missing parameter name at 1: https://git.new/pathToRegexpError followed by a backtrace which doesn't lead to my code. As a dev this is immediately problematic, as at first glance it looks like some bug in the library or incompatibility between dependencies. The impression is that the problem isn't actually in my code.
Furthermore the URL https://git.new/... does not appear legitimate at first glance (I've never seen the .new TLD before now) and looks like some kind of internal path. Since it just redirects to a github.com URL anyway, that URL should probably be used instead.
As the URL leads to a pillarjs repo page, I was further mislead into believing this was some kind of internal library error, as I do not use pillarjs or path-to-regexp and had not heard of it before now. There is no indication in the error shown or documentation that this has anything to do with my code, or with express which I would at least have recognized.
The documentation at that link states:
Missing parameter name
Parameter names must be provided after : or *, and they must be a valid JavaScript identifier. If you want an parameter name that isn't a JavaScript identifier, such as starting with a number, you can wrap the name in quotes like :"my-name".
This also does not mention express.
Ultimately I had to just dig through everywhere in my code where I was using * as some kind of parameter, change/comment it, and see if the error went away. This allowed me to narrow the issue down to express, and then to find this discussion.
Thank you @alandsidel, this is very helpful. I just released path-to-regexp@8.3.0 (which will automatically pull into new installs) because I didn't see any additional feedback on improving help but it comes with some changes that should help debug in the future:
It says visit http://... for more info so it's more obviously somewhere to click
It reduced the stack size internally to be 4 lines (so it should trace back to your application properly now)
As the URL leads to a pillarjs repo page
I wonder if it makes sense to try..catch the error in express or router and redirect to express docs? @wesleytodd @expressjs/express-tc Alternatively it could be a config option so you can inject it into the library error.
It says visit http://... for more info so it's more obviously somewhere to click
It does, but it still looks incorrect/suspicious/weird, and we all should know better than to click on suspicious looking links, so I didn't until after I'd solved it and was writing my comment to see if it was actually real or not. :)
It reduced the stack size internally to be 4 lines (so it should trace back to your application properly now)
This worked. I deleted package-lock.json and node_modules for a project using express 5.1.0 and reran npm i. package-lock.json says it pulled in path-to-regexp 8.3.0.
I put the old app.get('*'...) back in and it does now reference the correct line in my source file, so that's a big help.
As the URL leads to a pillarjs repo page
I wonder if it makes sense to try..catch the error in express or router and redirect to express docs? @wesleytodd @expressjs/express-tc
Yeah maybe? That was a tough one for me so I didn't really have a good suggestion here.
I do still think that a plain * should be regarded as a special token like *splat as it's not a valid regex pattern itself, since it has no preceding character identifier. Wasn't the change made in order to allow regex patterns? Maybe checking to see if the pattern is a valid regex and if it's not, then do the check for these types of reserved words?
It does, but it still looks incorrect/suspicious/weird
That's fair, I can update it in another release. The .new domain is often used by Google and others, e.g. docs.new. I used a redirect to avoid breaking the link unexpectedly for past releases, in case the docs were moved.
Wasn't the change made in order to allow regex patterns?
Not exactly, it was changed for better compatibility with the ecosystem of proxies and path rewriting, e.g. rewrite /api/*path to /api/v1/*path. There were also many edge cases in the Express 4 path routing due to * being confused with writing a regular expression (e.g. \d* would expand to \d.*) but that's less of an issue now the entire string isn't a magic regex.
Arguably it's better to have these be an error during the upgrade than to behave differently, but that's a separate can of worms since you could have written \d by itself and it's not behaving like a regex anymore. The error is only on modifiers like +, *, ?, [, and ].
I do still think that a plain * should be regarded as a special token like *splat as it's not a valid regex pattern itself
I'm not sure I understand this sentence, sorry. Can you clarify? There's no reserved words so I think maybe there's a miscommunication.
I'm referring to the special token *splat. I don't really know how to make that more clear?
*splat is not a special token. * introduces a wildcard parameter, which now must be named like : parameters. You can use /*literlallyAnythingThatYouWantAsLongAsItIsAValidIdentifier instead of /*splat. Both : and * capture values that can be accessed using req.params. The parameter name (e.g splat) that follows the * or : is the key name that will be present in req.params.
I'm referring to the special token *splat. I don't really know how to make that more clear?
*splat is not a special token. * introduces a wildcard parameter, which now must be named like : parameters. You can use /*literlallyAnythingThatYouWantAsLongAsItIsAValidIdentifier instead of /*splat. Both : and * capture values that can be accessed using req.params. The parameter name (e.g splat) that follows the * or : is the key name that will be present in req.params.
Ah, I see.
Well, IMNSHO the singular * should still be treated as it always was. My understanding is that currently it doesn't mean anything, correct? It's just an invalid wildcard? Falling back to treating it the way it was always treated historically strikes me as the right choice here.
Finally updating to v5, and this is hands down the most annoying part so far. All the other changes feel well founded but this one does not.
Wanting to apply effects to all OPTIONS requests for example.. Option 1: route.options('{/*foobar}', ...) and Option 2: route.options(/.*/, ...) is having to pick the lesser of two evils. The first form is ugly, the second form makes me cringe that I'm having to use regexp syntax for a function call that I'd prefer to be as branchless as possible. Even if the underlying resolution is identical in terms of branches it feels wrong and overly opinionated to force me to choose between nonsense words and having to write regular expressions. It's neither beginner friendly nor elegant.
Activity
mihaijulien commentedon Aug 18, 2025
This was a very annoying "breaking" change.
adiantek commentedon Aug 22, 2025
is there any workaround?
bjohansebas commentedon Aug 23, 2025
I really don’t know why the change was made and I’m not sure if reverting it would imply a breaking change.
cc: @blakeembrey
SergioNR commentedon Aug 23, 2025
Although it is not the intended usage, a workaround is using
app.use(‘*fallback’, req, res => { res.send(‘not found’} )At least that’s what I’m using for catch all routes
bjohansebas commentedon Aug 23, 2025
Actually, this is how it should be used in this version, the functionality was never removed, it's just that now it needs to be named. Please check the migration guide (https://expressjs.com/en/guide/migrating-5#path-syntax).
What I understand is that they want it to go back to how it was before, without having to name it.
Tanmay-008 commentedon Aug 23, 2025
(@bjohansebas )When we use (app.all('*', (req, res) => res.send('Not Found')); ) we get the error:(throw new TypeError(
Missing parameter name at ${i}: ${DEBUG_URL}); ). Can we update this? Because the error message does not explain anything clearly. It should be something that, when read, the user can understand what needs to be updated.Basically for beginners.blakeembrey commentedon Aug 23, 2025
@Tanmayshi Could you provide an example message of what could help you or someone else understand has broken better? I have a release ready that marginally improves this, but it isn’t a rewrite to the message, so it could still use your input to make it better.
SergioNR commentedon Aug 23, 2025
@Tanmayshi , from what I ve gathered from the docs,
app.all()should not be used to handle global catch all routers, butapp.use()instead. Maybe someone more knowledgeable can provide their insight tooApp.all()should be used when any req method should return the same response on any given endpoint - eg:GET
/healthPOST
/healthShould both return status 200
Tanmay-008 commentedon Aug 24, 2025
(@blakeembrey )You could make the message a bit more beginner-friendly so it’s easier to understand. Most beginners use Express, and the current message doesn’t really feel aligned with that perspective.
krzysdz commentedon Aug 24, 2025
pillarjs/path-to-regexp#363 will improve the message. It's been already merged and should be in the next
path-to-regexprelease.blakeembrey commentedon Aug 24, 2025
@Tanmayshi I understand you want it to be beginner friendly, I’m hoping to understand what would have helped you solve this. I hope it’s clear that I tried to make the errors friendly to begin with, and included a URL you could open to read more, in an attempt to make it beginner friendly already but it doesn’t seem to be enough.
alandsidel commentedon Aug 30, 2025
Ran into this myself today when updating an old project. I believe this change was a bad idea and can't intuitively see a reason to make
*splata special token; it seems like simply adding*as the special token would have worked just as well; a plain*with nothing preceding it is not a valid regex.That said, I agree the error messaging needs improvement. The message I saw is:
Uncaught Exception: TypeError: Missing parameter name at 1: https://git.new/pathToRegexpErrorfollowed by a backtrace which doesn't lead to my code. As a dev this is immediately problematic, as at first glance it looks like some bug in the library or incompatibility between dependencies. The impression is that the problem isn't actually in my code.Furthermore the URL
https://git.new/...does not appear legitimate at first glance (I've never seen the.newTLD before now) and looks like some kind of internal path. Since it just redirects to agithub.comURL anyway, that URL should probably be used instead.As the URL leads to a pillarjs repo page, I was further mislead into believing this was some kind of internal library error, as I do not use pillarjs or path-to-regexp and had not heard of it before now. There is no indication in the error shown or documentation that this has anything to do with my code, or with express which I would at least have recognized.
The documentation at that link states:
This also does not mention express.
Ultimately I had to just dig through everywhere in my code where I was using
*as some kind of parameter, change/comment it, and see if the error went away. This allowed me to narrow the issue down to express, and then to find this discussion.blakeembrey commentedon Sep 2, 2025
Thank you @alandsidel, this is very helpful. I just released
path-to-regexp@8.3.0(which will automatically pull into new installs) because I didn't see any additional feedback on improving help but it comes with some changes that should help debug in the future:visit http://... for more infoso it's more obviously somewhere to clickI wonder if it makes sense to
try..catchthe error in express or router and redirect to express docs? @wesleytodd @expressjs/express-tc Alternatively it could be a config option so you can inject it into the library error.alandsidel commentedon Sep 2, 2025
It does, but it still looks incorrect/suspicious/weird, and we all should know better than to click on suspicious looking links, so I didn't until after I'd solved it and was writing my comment to see if it was actually real or not. :)
This worked. I deleted
package-lock.jsonandnode_modulesfor a project using express 5.1.0 and rerannpm i.package-lock.jsonsays it pulled inpath-to-regexp8.3.0.I put the old
app.get('*'...)back in and it does now reference the correct line in my source file, so that's a big help.Yeah maybe? That was a tough one for me so I didn't really have a good suggestion here.
I do still think that a plain
*should be regarded as a special token like*splatas it's not a valid regex pattern itself, since it has no preceding character identifier. Wasn't the change made in order to allow regex patterns? Maybe checking to see if the pattern is a valid regex and if it's not, then do the check for these types of reserved words?Stabbing in the dark there a bit.
blakeembrey commentedon Sep 2, 2025
That's fair, I can update it in another release. The
.newdomain is often used by Google and others, e.g.docs.new. I used a redirect to avoid breaking the link unexpectedly for past releases, in case the docs were moved.Not exactly, it was changed for better compatibility with the ecosystem of proxies and path rewriting, e.g. rewrite
/api/*pathto/api/v1/*path. There were also many edge cases in the Express 4 path routing due to*being confused with writing a regular expression (e.g.\d*would expand to\d.*) but that's less of an issue now the entire string isn't a magic regex.Arguably it's better to have these be an error during the upgrade than to behave differently, but that's a separate can of worms since you could have written
\dby itself and it's not behaving like a regex anymore. The error is only on modifiers like+,*,?,[, and].I'm not sure I understand this sentence, sorry. Can you clarify? There's no reserved words so I think maybe there's a miscommunication.
trymeouteh commentedon Jan 23, 2026
Please bring back
*. It make the code simple to read.I cannot yet make the new wildcard paths work with my code since I have upgraded.
Muhammad-Rahim-2024 commentedon Feb 14, 2026
i tried in express v5 latest and app.get("/{splat}" is the only one that works for me
these dont work : app.get("/" , app.get("*" ,
alandsidel commentedon Mar 7, 2026
I'm referring to the special token
*splat. I don't really know how to make that more clear?app.get('/*splat', ....does not literally match the url path/*splat, it matches what*used to match before this change.krzysdz commentedon Mar 7, 2026
*splatis not a special token.*introduces a wildcard parameter, which now must be named like:parameters. You can use/*literlallyAnythingThatYouWantAsLongAsItIsAValidIdentifierinstead of/*splat. Both:and*capture values that can be accessed usingreq.params. The parameter name (e.gsplat) that follows the*or:is the key name that will be present inreq.params.alandsidel commentedon Mar 7, 2026
Ah, I see.
Well, IMNSHO the singular
*should still be treated as it always was. My understanding is that currently it doesn't mean anything, correct? It's just an invalid wildcard? Falling back to treating it the way it was always treated historically strikes me as the right choice here.mayfield commentedon Oct 5, 2026
Finally updating to v5, and this is hands down the most annoying part so far. All the other changes feel well founded but this one does not.
Wanting to apply effects to all OPTIONS requests for example.. Option 1:
route.options('{/*foobar}', ...)and Option 2:route.options(/.*/, ...)is having to pick the lesser of two evils. The first form is ugly, the second form makes me cringe that I'm having to use regexp syntax for a function call that I'd prefer to be as branchless as possible. Even if the underlying resolution is identical in terms of branches it feels wrong and overly opinionated to force me to choose between nonsense words and having to write regular expressions. It's neither beginner friendly nor elegant.ardenash commentedon Oct 5, 2026
alandsidel commentedon Oct 5, 2026
feat(backend)!: Phase 2 — Express 5, Mongoose 9 và tăng cường bảo mật