Everything was running well in production but after developing and locally testing some changes, deployment to production threw, out of nowhere, the following error: TypeError: Router.use() requires a middleware function
Full trace:
error Command failed with exit code 1.
at internal/main/run_main_module.js:17:47
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.<anonymous> (/home/node/dist/server.js:51:8)
at Function.use (/home/node/node_modules/express/lib/router/index.js:462:11)
TypeError: Router.use() requires a middleware function
^
throw new TypeError('Router.use() requires a middleware function')
/home/node/node_modules/express/lib/router/index.js:462
Because I didn't make any fundamental changes and all works well locally, it's quite a mystery where this opaque error comes from.
Has anybody had a similar problem in production?
The only place where Router.use() function is used is in server.ts file and that hasn't changed in the recent update.
server.ts
import payload from 'payload';
...
const router = express.Router();
router.use(payload.authenticate);
...
Do you want to create a new Router? express.Router(); returns a New Router Object. Instead, you can add the middleware directly to express.
const app = express();
const yourMiddleware = (req, res, next) => {
next();
};
app.get("/", (_, res) => { res.redirect("/admin"); });
app.use(yourMiddleware);
No, I haven't changed anything nor do I wish to change anything about this. It hasn't changed but the server failed to build this with any further new build. Even when I restored everything back to previously working code, the server now just doesn't run. Looks like a hosting provider issue?
Solved. Turns out it was the Payload npm package.
I was using the following version notation
"payload": "^1.4.1"
meaning all latest minor changes will be used.
Between now and 24 days ago since I last built a new image, something has changes in the way PayloadCMS works with Express and although it claims to be a
minorchange, it was a breaking change and something in the
server.tsfile related with express needs to be re-written.
I don't have time to do it now, so I reverted to using a strict version (1.4.1) of payload and it works. As soon as I use anything modern, it breaks.
I want to have my own custom routes (e.g. health check, and others) and I also need to access payload authentication middleware inside them.
So I followed tutorials on this but this doesn't work anymore in latest payload versions.
Here is my server.ts new router related code.
const router = express.Router();
router.use(payload.authenticate);
router.post('/transactions/process', (req: any, res) => {
if (req.user) {
return res.send(`Authenticated successfully as ${req.user.email}.`);
}
return res.send('Not authenticated');
});
router.get('/health', (req: any, res) => {
res.send('Healthy')
});
app.use('/custom', router);
app.listen(3000);
It works if await payload.init is before payload.authenticate.
const start = async () => {
const router = express.Router();
await payload.init({...}); // Changed to async. Need to wrap code into an async function
router.use(payload.authenticate);
router.post('/transactions/process', (req: any, res) => {
if (req.user) {
return res.send(`Authenticated successfully as ${req.user.email}.`);
}
return res.send('Not authenticated');
});
router.get('/health', (req: any, res) => {
res.send('Healthy')
});
app.use('/custom', router);
app.listen(3000);
}
start();
Same problem here.
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.