Skip to content

TypeError: Missing parameter name at 2: https://git.new/pathToRegexpError #6428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eru123 opened this issue Apr 1, 2025 · 25 comments
Open

Comments

@eru123
Copy link

eru123 commented Apr 1, 2025

Environment information

Version: v5.1.0

Platform: Linux 6.8.0-1021-aws 23~22.04.1-Ubuntu SMP Tue Dec 10 16:50:46 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Node.js version: v16.20.2

Any other relevant information: N/A

What steps will reproduce the bug?

# Installing the latest express cause the issue
npm install express

then throws error

TypeError: Missing parameter name at 2: https://git.new/pathToRegexpError
    at name (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:73:19)
    at lexer (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:91:27)
    at lexer.next (<anonymous>)
    at Iter.peek (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:106:38)
    at Iter.tryConsume (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:112:28)
    at Iter.text (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:128:30)
    at consume (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:152:29)
    at parse (/var/www/<project>/node_modules/path-to-regexp/dist/index.js:183:20)
    at /var/www/<project>/node_modules/path-to-regexp/dist/index.js:294:74
    at Array.map (<anonymous>)
/var/www/<project>/node_modules/path-to-regexp/dist/index.js:73
            throw new TypeError(`Missing parameter name at ${i}: ${DEBUG_URL}`);

Temporary Fix

Downgrade to 4.21.2

npm install express@4.21.2
@eru123 eru123 added the bug label Apr 1, 2025
@MrShadow50
Copy link

yes I got also same issue

@slagiewka
Copy link
Contributor

I you go to the DEBUG_URL: https://git.new/pathToRegexpError

You will see in the README:

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".

I would assume that your route contains *. Please confer the migration guide before opening issues: https://expressjs.com/en/guide/migrating-5.html#path-syntax

PS: Node.js version: v16.20.2 please note that express v5 requires node v18. Also note that node v16 has ben EoL since September 11th, 2023.

@wesleytodd
Copy link
Member

Yep, as @slagiewka says, please read our migration guide. v5 is a breaking upgrade, and you will need to make some changes to the path syntax you use. If you still think this is a bug after addressing the changes from the guide, please post the route definitions you have and we can take a look. I will leave this open only because I anticipate more folks asking the same question, but will remove the bug label as this is likely not a bug.

@wesleytodd wesleytodd removed the bug label Apr 1, 2025
@NetWin
Copy link

NetWin commented Apr 1, 2025

I had this problem aswell and can confirm that this is "simply" a breaking change from the V5 update.
As described in the changelogs here routes like app.use('/**', ...) are not supported anymore.

This problem came up while updating express in an Angular SSR application for me. When setting up SSR, Angular generated exactly the example mentioned above for me. But changing it to app.use('/{*path}', ...) fixed the problem for me. 👍

Screenshot from the migration section of the express homepage:

Image

@eru123
Copy link
Author

eru123 commented Apr 2, 2025

Thanks @wesleytodd and @slagiewka, I confirmed that it is a breaking issue with the new version.

As for our usecase we only have this one route, that accepts all requests and send in the index.html of our frontend build, and you guys are correct, this one is causing the issue.

app.get('/*', function (req, res) {
  res.sendFile(path.join(__dirname, '../build', 'index.html'));
});

I opened this issue yesterday because we have to rollback our production and it cost us downtime and delay our app release thinking it's a fault on our recent changes.

Funny enough, it's our mistake, we have this untouched code in our Dockerfile for ~5 years now and a package-lock.json is not generated until deployment as we do the expressjs installation on docker build, basically it's always installing the latest version 😭.

RUN npm install express

With this, I conclude that this issue is resolved, you guys can close this anytime if no one wants to add more. I just hope no major impact to production servers out there because of silly mistakes like what we did.

@MrShadow50
Copy link

@eru123 same with me I am using express to serve my react build and last 3-year code was working but because I also face same issue after this critical issue, I realize does not matter how much contributor are working on any lib it can have major issue after whole application.

@wesleytodd
Copy link
Member

This is true of all libraries, you have benefited these past years from the stability (and stagnation 😉) of the project. If you are doing something like npm install express in your build you need to specify a version you rely on. Change that to npm install express@5 now and then when we release v6 which will also include breaking changes you will avoid this pain.

I will still keep this open for now, because it avoids more duplicate issues, but glad to hear your issue is resolved @eru123!

@wesleytodd wesleytodd pinned this issue Apr 2, 2025
@wesleytodd
Copy link
Member

In fact, I just pinned this issue so that folks are more likely to see it than to open a new one.

ivictbor added a commit to devforth/adminforth that referenced this issue Apr 3, 2025
…y rollback express to v4 and spefcify in CLI that it should use v4 (latest-4 insted of latest), v5 requires additional migration steps expressjs/express#6428
@ManfredLange
Copy link

ManfredLange commented Apr 4, 2025

One case that creates this issue in my case is configuring CORS for pre-flight requests. In my case in express 4 the following worked:

this._app.options('*', corsSettings);

The first parameter here is a wild card which is no longer supported as such (without a name) in express 5.

For express 5 the following code works for me:

this._app.options(/.*/, corsSettings);

Note that in both cases the property this._app is defined as:

private readonly _app: express.Express = express();

Maybe this is of some value for others when upgrading to express version 5. Happy coding!

@noor-tg
Copy link

noor-tg commented Apr 4, 2025

Hi,

I have 2 routes like this

// error in this route
ApiRequestsRouter.get("/:request_id(\\d+)", ApiRequestsController.show);
ApiRequestsRouter.use([isAuth, isBand]);
ApiRequestsRouter.get("/mines", ApiRequestsController.mine);

In v4 this works. in v5 I see error about pathtoRegexpError Like the title

I can't use

// this route is protected by auth
ApiRequestsRouter.get("/mines", ApiRequestsController.mine);
// this is without auth
ApiRequestsRouter.get("/:request_id", ApiRequestsController.show);

so how to fix this for express v5.1 ?

@bjohansebas
Copy link
Member

I don't quite understand your problem, but from what I gather, you're having issues with /:request_id(\\d+). The solution would be to change it to /:request_id (as you already mentioned) and then check if :request_id is a number inside ApiRequestsController.show.

Is that the solution for now? Maybe @blakeembrey can confirm it.

@noor-tg
Copy link

noor-tg commented Apr 5, 2025

I don't quite understand your problem, but from what I gather, you're having issues with /:request_id(\\d+). The solution would be to change it to /:request_id (as you already mentioned) and then check if :request_id is a number inside ApiRequestsController.show.

Is that the solution for now? Maybe @blakeembrey can confirm it.

the problem is I have routes in same level. which handle other things. like /reqests/:request_id should only check /reqests/123 but not /requests/disagree

the only solution I found on route level is to add prefix to the id route. which is breaking change.

@bjohansebas bjohansebas marked this as a duplicate of #6441 Apr 7, 2025
@thetumper
Copy link

Not to poke the dead bear, but why were the path changes made? I guess many (at least myself), found the '*' more meaningful and understandable what it applied to, vs. '/{*something}'. I'm sure there was a reason, but is it helping the most people?

@wesleytodd
Copy link
Member

@thetumper this might help: https://blakeembrey.com/posts/2024-09-web-redos/

I think it is linked and called out in both the changelogs and original release announcement. Let us know if there are other places you looked but didn't see it so we can update those with description and links.

@TimoPot
Copy link

TimoPot commented Apr 18, 2025

When using Angular SSR and server.get('.',.... to do something with static files, make sure to change '.' into /.[a-zA-Z0-9]+$/

@Adam-Golan
Copy link

If you're trying to use '/**' and it doesn't work, there is a workaround: '/*\w'

@krzysdz
Copy link
Contributor

krzysdz commented Apr 22, 2025

If you're trying to use '/**' and it doesn't work, there is a workaround: '/*\w'

@Adam-Golan '/*\w' is equivalent to '/*w' (you're just escaping the letter w), which (in 5.x) matches a non-empty path (/ followed by anything) and captures it in req.params.w.
In 4.x '/**' would have two capture groups (the second one always empty, not sure why anybody would want it). For similar match (can be empty, but without the always empty param) in 5.x use '/{*something}'.

@Adam-Golan
Copy link

If you're trying to use '/**' and it doesn't work, there is a workaround: '/*\w'

@Adam-Golan '/*\w' is equivalent to '/*w' (you're just escaping the letter w), which (in 5.x) matches a non-empty path (/ followed by anything) and captures it in req.params.w. In 4.x '/**' would have two capture groups (the second one always empty, not sure why anybody would want it). For similar match (can be empty, but without the always empty param) in 5.x use '/{*something}'.

@krzysdz no it's not, it a metacharecter in regex and it covers all words, exactly like **.
The path argument is being digested as regex.

https://www.regextutorial.org/regular-expression-metacharacters.php

@krzysdz
Copy link
Contributor

krzysdz commented Apr 25, 2025

@Adam-Golan If you are using regular expressions directly, then yes - \w is a character class that matches word characters. However if you are using '\w' as a part of a string literal then it is equivalent to just 'w' (try console.log('\w')). If you want a string to contain a backslash, then it has to be escaped ('\\').

In both Express 4 and 5 you can pass a regular expression directly as a path (e.g. app.get(/^\/files\/(\w+\.(?:jpe?|pn)g)$/i, (req, res) => { /*...*/ })), but it has to be instanceof RegExp. Also in regular expressions * is a quantifier and quantifiers apply to immediately preceding token. There cannot be a quantifier that immediately follows another one (except for ?, which makes the previous one lazy) like in **.

According to Express Playground Router in Express 4, the route expression '/**' is converted to /^\/(.*)(.*)$/i RegExp (* was just converted to (.*)), which has two capture groups, and the second one is always empty (quantifiers are greedy by default, so .* in the first group matches everything after /). * in Express 4 was just an unnamed capture group that matches anything - even an empty sequence.

In Express 5, * behaves differently and must be followed by name - wildcards are no longer unnamed and match at least one character. A '/*literallyAnythingAsAName' route is converted to /^(?:\/([\s\S]+))(?:\/$)?$/i RegExp. Wildcard segments are converted to [\s\S]+.

In summary:

  • '/**' in Express 4 would match everything and create req.params[0] and req.params[1] ([1] always empty) - just use '/*',
  • '/**' in Express 5 is invalid, because wildcard parameters require a name and * is not a valid one - '/*"*"' would work and capture req.params['*'], that has at least one character,
  • '/*\w' is the same as '/*w' (that's how string literals in JS work) and in Express 5 would create a wildcard parameter that captures at least one character in req.params.w.

I really recommend experimenting with @bjohansebas' Express Playground Router if you want to understand how Express handles routes.

@eru123
Copy link
Author

eru123 commented Apr 25, 2025

@krzysdz on that case, if we ever use named capturing group in Regex as path (and not string literal) like this

/^\/files\/(?<resource>.*)$/i

is it possible to get the resource as parameter? or is there a workaround we can use to extract the resource from the path?

@krzysdz
Copy link
Contributor

krzysdz commented Apr 26, 2025

@krzysdz on that case, if we ever use named capturing group in Regex as path (and not string literal) like this

/^\/files\/(?<resource>.*)$/i

is it possible to get the resource as parameter? or is there a workaround we can use to extract the resource from the path?

If you use a named capturing group then it is available as req.params.groupName - req.params.resource in case of that expression. Unnamed groups are req.params[n].

@eru123
Copy link
Author

eru123 commented Apr 26, 2025

Great! I love using Regex all the time, that's a one great thing to have.

@Samuelplim
Copy link

In my case I had a route like in the example '/:file.:ext?' using @expressjs/codemod it was not possible to detect where it was, I was testing starting the server with small groups of files

@bjohansebas
Copy link
Member

@Samuelplim @expressjs/codemod doesn't modify routes, I don't understand what you mean.

@detobel36
Copy link

For people who use Angular, the upgrade has been done here: angular/angular-cli#29989

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests