Express 5 で「Missing parameter name」が出てサーバーが起動できない
Express 5 はルートのパスを path-to-regexp 8 で解析し、名前の無いワイルドカード * や、? と ( を含むパスをルート登録の時点で例外にする。
/* は /*splat(トップも含めるなら /{*splat})、/:id? は {/:id} のように書き換える。
公開: 更新:
要約
Express 4 で動いていたルートを Express 5 で登録すると、app.listen() に届く前に次の例外でプロセスが終了する。
PathError [TypeError]: Missing parameter name at index 2: /*; visit https://git.new/pathToRegexpError for infoExpress 5 はルートのパスの解析に path-to-regexp 8 を使っており、ワイルドカード * には :id と同じように名前が要る。? による省略可能なパラメータや、( などの正規表現の文字もパスの文字列には書けなくなった。移行ガイド(新しいタブで開く)の「Path route matching syntax」に変更点がまとまっている。
エラーの表記は path-to-regexp のバージョンで異なる。
上は Express 5.2.1 と、依存として入る path-to-regexp 8.4.2 での表示で、いま Express 5.0.1〜5.2.1 のどれを入れても同じ表示になった。
8.3.0 から例外のクラスが TypeError を継承した PathError に変わっており、上の表示の先頭が PathError [TypeError] になっているのはそのためだ。
8.2.0 では TypeError: Missing parameter name at 2: https://git.new/pathToRegexpError の形で出る。
どちらも末尾の URL は path-to-regexp の README のエラー一覧を指す。
よくある原因
- 名前の無い
*: Express 4 時代の記事でよく見るapp.get('*', ...)(SPA のフォールバック)やapp.use('/api/*', ...)が、そのまま例外になる。 ?で省略可能なパラメータ:/user/:id?はUnexpected ?で始まる例外になる。- パスの文字列に正規表現の文字:
/:section(discussion|page)/:slugのような書き方はUnexpected (で始まる例外になる。 - 5 系が入ったことに気付いていない: 2025 年 3 月末に npm の
latestタグが 5.1.0 に切り替わり、バージョンを指定しないnpm install expressで 5 系が入るようになった。
解決策
1. ワイルドカードに名前を付ける
// Express 4
app.get("/files/*", handler);
// Express 5
app.get("/files/*splat", handler);一致した部分は req.params.splat に配列で入り、/files/a/b.txt なら ["a", "b.txt"] になる。*splat は 1 文字以上に一致するので、/*splat はトップの / に一致しない。
トップも含めてすべてのパスに一致させたいときは、波括弧で囲んで /{*splat} と書く。
app.get("/{*splat}", (req, res) => {
res.sendFile(path.join(__dirname, "dist", "index.html"));
});2. 省略可能な部分は波括弧で囲む
// Express 4
app.get("/user/:id?", handler);
// Express 5(/user と /user/42 の両方に一致する)
app.get("/user{/:id}", handler);波括弧の中は丸ごと省略できる。
拡張子を省略可能にするなら /:file{.:ext} と書く。
3. 正規表現が要るときは配列か正規表現リテラルで渡す
// パスを候補ごとに並べる
app.get(["/discussion/:slug", "/page/:slug"], handler);
// 正規表現リテラルで渡す(キャプチャは req.params[0] と req.params[1] に入る)
app.get(/^\/(discussion|page)\/([^/]+)$/, handler);正規表現の文字が使えないのは文字列で渡した場合で、RegExp をそのまま渡すことはできる。
4. 移行を後回しにするなら 4 系を指定する
npm install express@44 系は 5.1.0 が latest になった時点で保守フェーズ(MAINTENANCE)に移っている。
4 系に固定するのは移行までのつなぎとし、パスの書き換えを済ませたら 5 系に戻す。