Introduction
Handling errors properly in an API is crucial for debugging, logging, and user experience. Yet, many developers still make common mistakes that lead to vague error messages, inconsistent status codes, or security risks.
In this post, we’ll go through 10 common API error-handling mistakes and how to fix them using http-error-kit
for clean, structured error responses. With http-error-kit
, predefined error classes like BadRequestError
, NotFoundError
, and InternalServerError
make error handling more readable and maintainable.
1. Missing Proper HTTP Status Codes
A classic mistake is sending the wrong status code—or worse, not setting one at all!
Bad Example:
res.status(200).json({ error: "Not Found" }); // Incorrect 200 status for an error
Fix: Always use proper HTTP status codes.
With http-error-kit
:
import { NotFoundError } from "http-error-kit";
throw new NotFoundError("Resource not found");
By using NotFoundError
, the status code is automatically set to 404, keeping the code clean and readable.
2. Using console.log(error)
Instead of Proper Logging
Dumping errors into console.log
isn’t useful in production. It makes debugging harder and provides no structured response to clients.
Bad Example:
try {
throw new Error("Something went wrong");
} catch (err) {
console.log(err); // Logs error but doesn't return a response
}
Fix: Use structured error handling and logging.
app.use((err, req, res, next) => {
console.error(err); // Logs for debugging
res.status(err.statusCode || 500).json(err);
});
3. Revealing Internal Errors to Clients
Returning raw error objects can expose sensitive information to attackers.
Bad Example:
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message, stack: err.stack }); // Never expose stack traces
});
Fix: Send only necessary details to the client.
app.use((err, req, res, next) => {
res.status(err.statusCode || 500).json({ error: err.message });
});
For structured errors, use http-error-kit
:
throw new InternalServerError("Something went wrong");
4. Catching Errors Without Handling Them
Some developers catch errors but don’t handle them, making debugging harder.
Bad Example:
try {
// API call
} catch (err) {
// Error is caught but nothing happens
}
Fix: Always return a response.
import { BadRequestError } from "http-error-kit";
try {
throw new BadRequestError("Invalid input");
} catch (err) {
res.status(err.statusCode).json(err);
}
5. Not Handling Asynchronous Errors
Forgetting to handle async errors can crash the entire Node.js process.
Bad Example:
app.get("/data", (req, res) => {
const result = fetchData(); // Missing try/catch
res.json(result);
});
Fix: Wrap async functions in try/catch
.
import { InternalServerError } from "http-error-kit";
app.get("/data", async (req, res, next) => {
try {
const result = await fetchData();
res.json(result);
} catch (err) {
next(new InternalServerError("Failed to fetch data"));
}
});
6. Using throw
in Express Routes Without Handling It
Express doesn’t automatically catch throw
statements inside routes.
Bad Example:
app.get("/", (req, res) => {
throw new Error("Unexpected error"); // This crashes the server!
});
Fix: Pass errors to next()
.
import { InternalServerError } from "http-error-kit";
app.get("/", (req, res, next) => {
next(new InternalServerError("Something went wrong"));
});
Conclusion
Handling API errors properly improves debugging, security, and user experience. Instead of writing error-handling logic from scratch, use http-error-kit
for structured, consistent error responses. Its built-in error classes (BadRequestError
, NotFoundError
, InternalServerError
, etc.) make code more readable and maintainable.
🔥 Try it now:
npm install http-error-kit
👉 Star it on GitHub: GitHub Repository
Top comments (0)