How can I get Express.js to 404 only on missing routes?

You just need to put it at the end of all route.

Take a look at the second example of Passing Route Control:

var express = require('express')
  , app = express.createServer();

var users = [{ name: 'tj' }];

app.all('/user/:id/:op?', function(req, res, next){
  req.user = users[req.params.id];
  if (req.user) {
    next();
  } else {
    next(new Error('cannot find user ' + req.params.id));
  }
});

app.get('/user/:id', function(req, res){
  res.send('viewing ' + req.user.name);
});

app.get('/user/:id/edit', function(req, res){
  res.send('editing ' + req.user.name);
});

app.put('/user/:id', function(req, res){
  res.send('updating ' + req.user.name);
});

app.get('*', function(req, res){
  res.send('what???', 404);
});

app.listen(3000); 

Alternatively you can do nothing because all route which does not match will produce a 404. Then you can use this code to display the right template:

app.error(function(err, req, res, next){
    if (err instanceof NotFound) {
        res.render('404.jade');
    } else {
        next(err);
    }
});

It's documented in Error Handling.


I bet your browser is following up with a request for the favicon. That is why you are seeing the 404 in your logs after the 200 success for the requested page.

Setup a favicon route.


Hope it helpful, I used this code in bottom of routes

router.use((req, res, next) => {
    next({
        status: 404,
        message: 'Not Found',
    });
});

router.use((err, req, res, next) => {
    if (err.status === 404) {
        return res.status(400).render('404');
    }

    if (err.status === 500) {
        return res.status(500).render('500');
    }

   next();
});

You can this at the end of all routes,

const express = require('express');
const app = express();
const port = 8080;

// All your routes and middleware here.....

app.use((req, res, next) => {
    res.status(404).json({
        message: 'Ohh you are lost, read the API documentation to find your way back home :)'
    })
})

// Init the server here,
app.listen( port, () => {
    console.log('Sever is up')
})

I wanted a catch all that would render my 404 page only on missing routes and found it here in the error handling docs https://expressjs.com/en/guide/error-handling.html

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(404).render('404.ejs')
})

This worked for me.