できない.dev

Express「Router.use() requires a middleware function」の原因と直し方

Router.use() requires a middleware function は、ルーターのファイルに module.exports = router を書けば直ることが多い。
Express 5 では argument handler must be a function と出る。

公開: 更新:

症状できない · exit 1
node app.js
…
      throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
      ^
TypeError: Router.use() requires a middleware function but got a Object

2026-11-03 に node:22(Node.js 22.23.4 / npm 10.9.9) で実際に打って取った出力。検証環境の詳細

要約

ルーターを別ファイルに分けて app.use("/users", require("./routes/users")) と書いたところ、サーバーが起動する前に止まった。
Express 4.22.3(Node.js 22)では次のように出た。

TypeError: Router.use() requires a middleware function but got a Object
    at Function.use (/app/node_modules/express/lib/router/index.js:469:13)
    at Function.<anonymous> (/app/node_modules/express/lib/application.js:227:21)
    at Array.forEach (<anonymous>)
    at Function.use (/app/node_modules/express/lib/application.js:224:7)
    at Object.<anonymous> (/app/app.js:3:5)

Express 5.3.0 では、同じコードでも文言が変わる。

TypeError: argument handler must be a function

どちらも、app.use() に関数ではない値を渡しているという意味だ。
ルーター(express.Router() が返すもの)もミドルウェアも関数なので、require() が関数を返していないと、登録した時点で落ちる。

実行例

Express 4.22.3 では、app.use() に渡した値の型がエラー文に Object・undefined・Module と出て、終了コードはどれも 1 だった。
Express 5.3.0 では argument handler must be a function となり、渡した値の型は出なかった。

$ node --version
v22.23.4
$ npm ls express
router-demo@ /tmp/tmp.qxTB6ycoza
`-- express@4.22.3
$ node app.js
/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469
      throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
      ^
 
TypeError: Router.use() requires a middleware function but got a Object
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469:13)
    at Function.<anonymous> (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:227:21)
    at Array.forEach (<anonymous>)
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:224:7)
    at Object.<anonymous> (/tmp/tmp.qxTB6ycoza/app.js:4:5)
    at Module._compile (node:internal/modules/cjs/loader:1781:14)
    at Object..js (node:internal/modules/cjs/loader:1913:10)
    at Module.load (node:internal/modules/cjs/loader:1505:32)
    at Function._load (node:internal/modules/cjs/loader:1309:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:254:19)
 
Node.js v22.23.4
$ echo $?
1
$ node app.js
/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469
      throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
      ^
 
TypeError: Router.use() requires a middleware function but got a Object
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469:13)
    at Function.<anonymous> (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:227:21)
    at Array.forEach (<anonymous>)
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:224:7)
    at Object.<anonymous> (/tmp/tmp.qxTB6ycoza/app.js:4:5)
    at Module._compile (node:internal/modules/cjs/loader:1781:14)
    at Object..js (node:internal/modules/cjs/loader:1913:10)
    at Module.load (node:internal/modules/cjs/loader:1505:32)
    at Function._load (node:internal/modules/cjs/loader:1309:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:254:19)
 
Node.js v22.23.4
$ echo $?
1
$ node app.js
/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469
      throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
      ^
 
TypeError: Router.use() requires a middleware function but got a undefined
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/router/index.js:469:13)
    at Function.<anonymous> (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:227:21)
    at Array.forEach (<anonymous>)
    at Function.use (/tmp/tmp.qxTB6ycoza/node_modules/express/lib/application.js:224:7)
    at Object.<anonymous> (/tmp/tmp.qxTB6ycoza/app.js:5:5)
    at Module._compile (node:internal/modules/cjs/loader:1781:14)
    at Object..js (node:internal/modules/cjs/loader:1913:10)
    at Module.load (node:internal/modules/cjs/loader:1505:32)
    at Function._load (node:internal/modules/cjs/loader:1309:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:254:19)
 
Node.js v22.23.4
$ echo $?
1

— 2026-11-03 時点の出力

検証環境Node.js 22.23.4 / npm 10.9.9 / Python 3.11.2 / 2026-11-03 検証(ほか 1 件)
検証日
実行環境
node:22 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 22.23.4
  • npm 10.9.9
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

1. ルーターを書き出す

// routes/users.js
const express = require("express");
const router = express.Router();
 
router.get("/", (req, res) => res.json([{ name: "user" }]));
 
module.exports = router;

この 1 行を足すと起動し、curl localhost:3000/users に [{"name":"user"}] が返った(Express 4・5 とも)。
書き方は公式のルーティングのガイド(新しいタブで開く)の express.Router の例と同じだ。

2. 書き出した形に合わせて取り出す

const { usersRouter } = require("./routes/users"); // exports.usersRouter = router のとき
app.use("/users", usersRouter);

渡す前に console.log(typeof usersRouter) を挟み、function と出るかを見ると原因を早く絞れる。

3. ES モジュールは .default を付ける

app.use("/users", require("./routes/users.mjs").default);

require() で ES モジュールを読み込むと、書き出したものはモジュールの名前空間オブジェクトに入る。export default したものは .default で取り出すと通った(Node.js 22.23.3)。
アプリ全体を ES モジュールにするなら import usersRouter from "./routes/users.mjs" と書く。

よくある原因

  1. module.exports = router を書き忘れている。
    書き出していないファイルを require() すると空のオブジェクト {} が返り、got a Object になる。
  2. オブジェクトに包んで書き出している。module.exports = { router } なら、渡すべきは .router の中身だ。
    そのまま渡すと同じく got a Object になる。
  3. 書き出した名前と読み込む名前が食い違っている。exports.usersRouter = router で書き出して const { router } = require(...) で読むと undefined が入り、got a undefined になった。
  4. ES モジュールを require した。export default router のファイルを require() すると、got a Module になった。

Express 5 では 1〜4 のどれも argument handler must be a function になり、渡した値の型は出ない。