The 404 page and error handling
When no route matches, Express answers with a terse "Cannot GET /address". And if a handler hits an error, the visitor sees technical text with code. Both situations are caught with your own middleware at the very end of src/app.js.
The 404 page
Middleware added after all routes receives only the requests nobody handled:
// src/app.js
app.use('/posts', postsRouter);
app.use((req, res) => {
res.status(404).send('<h1>Page not found</h1><a href="/posts">To the posts</a>');
});Open http://localhost:3000/nothing and you see the heading "Page not found" and a link to the list of posts. Once the course reaches templates, this becomes res.status(404).render('404').
The error handler
An error handler differs from ordinary middleware in that it takes four arguments. The error itself comes first:
// src/app.js
app.use((error, req, res, next) => {
console.error(error);
res.status(500).send('<h1>Something went wrong</h1>');
});It goes last, after the 404 page. The error details are written to the terminal for the developer, and the visitor sees a calm message.
How an error gets there
If an exception is thrown in a route handler, Express catches it and passes it to the error handler:
// src/controllers/postsController.js
export function show(req, res) {
const post = posts.find((item) => item.id === Number(req.params.id));
if (!post) {
const error = new Error('Post not found');
error.status = 404;
throw error;
}
res.send(post.title);
}You can also pass an error explicitly by calling next(error). Anything passed to next as an argument is treated by Express as an error, and ordinary middleware is skipped.
The status code from the error
So that one handler can answer both 404 and 500, take the code from the error:
// src/app.js
app.use((error, req, res, next) => {
const status = error.status ?? 500;
if (status === 500) {
console.error(error);
}
res.status(status).send(status === 404 ? 'Not found' : 'Server error');
});Now /posts/99 returns "Not found" with code 404, and a real failure returns "Server error" with code 500 and a record in the terminal.
Order in app.js
| Place | What is added |
|---|---|
| Top | Shared middleware: body parsing, static files |
| Middle | Routes |
| Second to last | The 404 page |
| Last | The error handler |
Common mistake
Express recognises an error handler only by its number of arguments. If you write (error, req, res) => ... without next, the function has three arguments and counts as ordinary middleware — errors never reach it. Always list all four parameters, even if next is unused.