
Security News
Node.js Drops Bug Bounty Rewards After Funding Dries Up
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.
express-pretty-errors
Advanced tools
Pretty HTML error pages and helpers for Express (404 + 500), with JSON fallback.
🧭 Elegant, dark/light-mode–aware error pages for Express — with JSON fallback, theme & logo support.
404 and 500+ errorslocalStorage)asyncWrap(fn) for async route errorsrenderWithNext(res, view, data, next) for safe template renderingnpm install express-pretty-errors
# or
yarn add express-pretty-errors
Your project must already have Express installed (declared as a peer dependency).
const express = require("express");
const { notFound, errorHandler } = require("express-pretty-errors");
const app = express();
// Example route that throws an error
app.get("/boom", () => { throw new Error("Kaboom!"); });
// Your normal routes go here...
// 404 handler (no route matched)
app.use(notFound());
// 500+ handler (something threw)
app.use(errorHandler({ showStack: "dev" }));
app.listen(3000, () => console.log("→ http://localhost:3000"));
Visit:
/boom → shows a pretty 500 error page/nope → shows a pretty 404 pagenotFound(options?)Handles missing routes (404 Not Found).
| Option | Type | Default | Description |
|---|---|---|---|
theme | "auto" | "light" | "dark" | "auto" | Force a theme or follow OS setting |
cssVars | object | — | Override CSS variables (see below) |
showThemeToggle | boolean | false | Adds a light/dark/auto toggle button |
logoUrl | string | — | URL or path to logo image (SVG/PNG) |
logoAlt | string | "Logo" | Alt text for the logo |
logoHref | string | "/" | Click-through URL for the logo |
logoHeight | number | 28 | Max height in px |
brandName | string | — | Optional text label next to logo |
links | [{ href, label }] | — | Helpful quick links section |
jsonOnly | boolean | false | Always respond with JSON instead of HTML |
errorHandler(options?)Handles thrown errors or rejected promises (500+).
Same options as notFound, plus:
| Option | Type | Default | Description |
|---|---|---|---|
showStack | "always" | "never" | "dev" | "dev" | Show stack traces in development only |
asyncWrap(fn)Wraps async route handlers to automatically catch rejections.
const { asyncWrap } = require("express-pretty-errors");
app.get("/data", asyncWrap(async (req, res) => {
const rows = await db.query("SELECT * FROM items");
res.json(rows);
}));
No need for try/catch—errors go straight to errorHandler.
renderWithNext(res, view, data, next)Wraps res.render safely; forwards template errors to your errorHandler.
const { renderWithNext } = require("express-pretty-errors");
app.get("/about", (req, res, next) => {
renderWithNext(res, "about", { title: "About Us" }, next);
});
app.use(errorHandler({ theme: "dark" }));
app.use(notFound({ theme: "light" }));
app.use(errorHandler({
theme: "auto",
cssVars: {
accent: "#10b981", // teal accent
panel: "#111827", // custom dark panel
light_accent: "#059669" // light mode accent
}
}));
app.use(errorHandler({
theme: "auto",
logoUrl: "/assets/logo.svg",
logoAlt: "Acme Inc.",
logoHref: "/",
brandName: "Acme Inc.",
showThemeToggle: true
}));
notFound({
links: [
{ href: "/", label: "Home" },
{ href: "/contact", label: "Contact Support" },
{ href: "/search?q=", label: "Search" }
]
});
data-theme attribute is set on <html>.@media (prefers-color-scheme: light) to detect system preference.data-theme="light" or "dark" and stores the preference in localStorage.express-pretty-errors/
├─ package.json
├─ index.js
├─ template.js
├─ README.md
└─ examples/
├─ public/
│ └─ logo.svg
└─ server.js
examples/server.js
const express = require("express");
const { notFound, errorHandler } = require("..");
const app = express();
app.use(express.static(__dirname + "/public"));
app.get("/", (_req, res) => res.send(`<a href="/boom">500</a> • <a href="/nope">404</a>`));
app.get("/boom", () => { throw new Error("Kaboom!"); });
app.use(notFound({
theme: "auto",
logoUrl: "/logo.svg",
brandName: "Acme",
showThemeToggle: true
}));
app.use(errorHandler({
showStack: "dev",
theme: "auto",
logoUrl: "/logo.svg",
brandName: "Acme",
showThemeToggle: true
}));
app.listen(3000, () => console.log("→ http://localhost:3000"));
Run the example:
node examples/server.js
Then visit:
Or test JSON responses:
curl -H "Accept: application/json" http://localhost:3000/boom
| Code | Type | Who’s at Fault | Description |
|---|---|---|---|
| 404 | Client Error | The client | The route/resource doesn’t exist. |
| 500 | Server Error | The server | Something broke while handling a valid request. |
Your notFound() middleware catches 404s.
Your errorHandler() middleware catches 500s and other thrown errors.
MIT © [Your Name]
Designed and maintained by CloseRange (Michael Hulbert) Inspired by a desire for nicer default Express error pages.
FAQs
Pretty HTML error pages and helpers for Express (404 + 500), with JSON fallback.
We found that express-pretty-errors demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.