[node.js] How to redirect 404 errors to a page in ExpressJS?

I don't know a function for doing this, does anyone know of one?

This question is related to node.js express

The answer is


You can put a middleware at the last position that throws a NotFound error,
or even renders the 404 page directly:

app.use(function(req,res){
    res.status(404).render('404.jade');
});

The easiest way to do it is to have a catch all for Error Page

// Step 1: calling express
const express = require("express");
const app = express();

Then

// require Path to get file locations
const path = require("path");

Now you can store all your "html" pages (including an error "html" page) in a variable

// Storing file locations in a variable
var indexPg = path.join(__dirname, "./htmlPages/index.html");
var aboutPg = path.join(__dirname, "./htmlPages/about.html");
var contactPg = path.join(__dirname, "./htmlPages/contact.html");
var errorPg = path.join(__dirname, "./htmlPages/404.html"); //this is your error page

Now you simply call the pages using the Get Method and have a catch all for any routes not available to direct to your error page using app.get("*")

//Step 2: Defining Routes
//default page will be your index.html
app.get("/", function(req,res){
  res.sendFile(indexPg);
});
//about page
app.get("/about", function(req,res){
  res.sendFile(aboutPg);
});
//contact page
app.get("/contact", function(req,res){
  res.sendFile(contactPg);
});
//catch all endpoint will be Error Page
app.get("*", function(req,res){
  res.sendFile(errorPg);
});

Don't forget to set up a Port and Listen for server:

// Setting port to listen on
const port = process.env.PORT || 8000;
// Listening on port
app.listen(port, function(){
  console.log(`http://localhost:${port}`);
})

This should now show your error page for all unrecognized endpoints!


To send to a custom page:

app.get('*', function(req, res){
  if (req.accepts('html')) {
     res.send('404', '<script>location.href = "/the-404-page.html";</script>');
     return;
  }
});

If you want to redirect to error pages from your functions (routes) then do following things -

  1. Add general error messages code in your app.js -

    app.use(function(err, req, res, next) {
        // set locals, only providing error in development
        res.locals.message = err.message
        res.locals.error = req.app.get('env') === 'development' ? err : {}
    
        // render the error page
        // you can also serve different error pages
        // for example sake, I am just responding with simple error messages 
        res.status(err.status || 500)
       if(err.status === 403){
           return res.send('Action forbidden!');
       }
    
       if(err.status === 404){
           return res.send('Page not found!');
       }
    
       // when status is 500, error handler
       if(err.status === 500) {
           return res.send('Server error occured!');
       }
       res.render('error')
    })
    
  2. In your function, instead of using a error-page redirect you can use set the error status first and then use next() for the code flow to go through above code -

    if(FOUND){
        ...
    }else{
        // redirecting to general error page
        // any error code can be used (provided you have handled its error response)
        res.status(404)
        // calling next() will make the control to go call the step 1. error code
        // it will return the error response according to the error code given (provided you have handled its error response)
        next()
    }
    

The above answers are good, but in half of these you won't be getting 404 as your HTTP status code returned and in other half, you won't be able to have a custom template render. The best way to have a custom error page (404's) in Expressjs is

app.use(function(req, res, next){
    res.status(404).render('404_error_template', {title: "Sorry, page not found"});
});

Place this code at the end of all your URL mappings.


Hi please find the answer

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

app.get('/', (req, res) => res.send('Hello home!'));
app.get('/about-us', (req, res) => res.send('Hello about us!'));
app.post('/user/set-profile', (req, res) => res.send('Hello profile!'));
//last 404 page 
app.get('*', (req, res) => res.send('Page Not found 404'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));

The answer to your question is:

app.use(function(req, res) {
    res.status(404).end('error');
});

And there is a great article about why it is the best way here.


// Add this middleware
// error handler
app.use(function(err, req, res, next) {
 // set locals, only providing error in development
   res.locals.message = err.message;
   res.locals.error = req.app.get('env') === 'development' ? err : {};

 // render the error page
   res.status(err.status || 500);
   res.render('error');
  });

express-error-handler lets you specify custom templates, static pages, or error handlers for your errors. It also does other useful error-handling things that every app should implement, like protect against 4xx error DOS attacks, and graceful shutdown on unrecoverable errors. Here's how you do what you're asking for:

var errorHandler = require('express-error-handler'),
  handler = errorHandler({
    static: {
      '404': 'path/to/static/404.html'
    }
  });

// After all your routes...
// Pass a 404 into next(err)
app.use( errorHandler.httpError(404) );

// Handle all unhandled errors:
app.use( handler );

Or for a custom handler:

handler = errorHandler({
  handlers: {
    '404': function err404() {
      // do some custom thing here...
    }
  }
}); 

Or for a custom view:

handler = errorHandler({
  views: {
    '404': '404.jade'
  }
});


Covering of all HTTP verbs in express

In order to cover all HTTP verbs and all remaining paths you could use:

app.all('*', cb)

Final solution would look like so:

app.all('*', (req, res) =>{
    res.status(404).json({
        success: false,
        data: '404'
    })
})

You shouldn't forget to put the router in the end. Because order of routers matter.


While the answers above are correct, for those who want to get this working in IISNODE you also need to specify

<configuration>
    <system.webServer>
        <httpErrors existingResponse="PassThrough"/>
    </system.webServer>
<configuration>

in your web.config (otherwise IIS will eat your output).


What I do after defining all routes is to catch potential 404 and forward to error handler, like this:

    const httpError = require('http-errors');

    ...

    // API router
    app.use('/api/', routes);
    
    // catch 404 and forward to error handler
    app.use((req, res, next) => {
      const err = new httpError(404)
      return next(err);
    });

    module.exports = app;

you can error handling according to content-type

Additionally, handling according to status code.

app.js

import express from 'express';

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// when status is 404, error handler
app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    if( 404 === err.status  ){
        res.format({
            'text/plain': () => {
                res.send({message: 'not found Data'});
            },
            'text/html': () => {
                res.render('404.jade');
            },
            'application/json': () => {
                res.send({message: 'not found Data'});
            },
            'default': () => {
                res.status(406).send('Not Acceptable');
            }
        })
    }

    // when status is 500, error handler
    if(500 === err.status) {
        return res.send({message: 'error occur'});
    }
});

404.jade

doctype html

html
  head
    title 404 Not Found

    meta(http-equiv="Content-Type" content="text/html; charset=utf-8")
    meta(name = "viewport" content="width=device-width, initial-scale=1.0 user-scalable=no")

  body
      h2 Not Found Page
      h2 404 Error Code

If you can using res.format, You can write simple error handling code.

Recommendation res.format() instead of res.accepts().

If the 500 error occurs in the previous code, if(500 == err.status){. . . } is called


The above code didn't work for me.

So I found a new solution that actually works!

app.use(function(req, res, next) {
    res.status(404).send('Unable to find the requested resource!');
});

Or you can even render it to a 404 page.

app.use(function(req, res, next) {
    res.status(404).render("404page");
});

Hope this helped you!


I think you should first define all your routes and as the last route add

//The 404 Route (ALWAYS Keep this as the last route)
app.get('*', function(req, res){
  res.status(404).send('what???');
});

An example app which does work:

app.js:

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

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
  res.send('hello world');
});

//The 404 Route (ALWAYS Keep this as the last route)
app.get('*', function(req, res){
  res.send('what???', 404);
});

app.listen(3000, '127.0.0.1');

alfred@alfred-laptop:~/node/stackoverflow/6528876$ mkdir public
alfred@alfred-laptop:~/node/stackoverflow/6528876$ find .
alfred@alfred-laptop:~/node/stackoverflow/6528876$ echo "I don't find a function for that... Anyone knows?" > public/README.txt
alfred@alfred-laptop:~/node/stackoverflow/6528876$ cat public/README.txt 

.
./app.js
./public
./public/README.txt

alfred@alfred-laptop:~/node/stackoverflow/6528876$ curl http://localhost:3000/
hello world
alfred@alfred-laptop:~/node/stackoverflow/6528876$ curl http://localhost:3000/README.txt
I don't find a function for that... Anyone knows?

I used the handler below to handle 404 error with a static .ejs file.

Put this code in a route script and then require that file.js through app.use() in your app.js/server.js/www.js (if using IntelliJ for NodeJS)

You can also use a static .html file.

//Unknown route handler
 router.get("[otherRoute]", function(request, response) {
     response.status(404);
     response.render("error404.[ejs]/[html]");
     response.end();
 });

This way, the running express server will response with a proper 404 error and your website can also include a page that properly displays the server's 404 response properly. You can also include a navbar in that 404 error template that links to other important content of your website.


If you use express-generator package:

next(err);

This code send you to the 404 middleware.


There are some cases where 404 page cannot be written to be executed as the last route, especially if you have an asynchronous routing function that brings in a /route late to the party. The pattern below might be adopted in those cases.

var express = require("express.io"),
    app = express(),
    router = express.Router();

router.get("/hello", function (req, res) {
    res.send("Hello World");
});

// Router is up here.
app.use(router);

app.use(function(req, res) {
    res.send("Crime Scene 404. Do not repeat");
});

router.get("/late", function (req, res) {
    res.send("Its OK to come late");
});

app.listen(8080, function (){
    console.log("Ready");
});

app.get('*',function(req,res){
 res.redirect('/login');
});

The 404 page should be set up just before the call to app.listen.Express has support for * in route paths. This is a special character which matches anything. This can be used to create a route handler that matches all requests.

app.get('*', (req, res) => {
  res.render('404', {
    title: '404',
    name: 'test',
    errorMessage: 'Page not found.'
  })
})

At the last line of app.js just put this function. This will override the default page-not-found error page:

app.use(function (req, res) {
    res.status(404).render('error');
});

It will override all the requests that don't have a valid handler and render your own error page.


Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to express

UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block jwt check if token expired Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] npm notice created a lockfile as package-lock.json. You should commit this file Make Axios send cookies in its requests automatically What does body-parser do with express? SyntaxError: Unexpected token function - Async Await Nodejs Route.get() requires callback functions but got a "object Undefined" How to redirect to another page in node.js