Handling Errors and HTTP Status Codes in APIs
Throw errors like a pro
Last updated: 3/5/2025
Handling Errors and HTTP Status Codes in APIs
π Introduction
In a RESTful API, error handling is crucial for providing clear and useful feedback to clients.
When something goes wrong (e.g., invalid input, unauthorized access, server issues), the API should:
- Return a meaningful error message.
- Use the correct HTTP status code.
- Follow a consistent error response format.
In this lesson, you'll learn:
- Common HTTP status codes for success and errors.
- How to handle client-side vs. server-side errors.
- Best practices for structuring error responses.
π 1. Understanding HTTP Status Codes
HTTP status codes indicate the result of a request.
They are divided into different categories:
Code Range | Type | Description |
---|---|---|
2xx | β Success | Request was successful. |
3xx | π Redirection | Client needs to follow another URL. |
4xx | β οΈ Client Errors | Something is wrong with the request. |
5xx | π₯ Server Errors | Something is wrong with the server. |
β Common HTTP Status Codes
Code | Name | Meaning |
---|---|---|
200 | OK | Successful request. |
201 | Created | Resource created successfully. |
400 | Bad Request | The request is invalid (e.g., missing required fields). |
401 | Unauthorized | Authentication is required. |
403 | Forbidden | User doesnβt have permission. |
404 | Not Found | The resource does not exist. |
409 | Conflict | Data conflict (e.g., duplicate username). |
500 | Internal Server Error | Something went wrong on the server. |
π 2. Client Errors (4xx)
Client errors occur when the request is incorrect.
Example: A user tries to fetch a non-existent user.
β Bad Example (No Proper Error Handling)
app.get('/users/:id', (req, res) => { const user = null; // Simulating user not found res.json(user); // β This will return null instead of an error });
β Good Example (Proper Error Handling)
app.get('/users/:id', (req, res) => { const user = null; // Simulating user not found if (!user) { return res.status(404).json({ error: "User not found", message: "The user with the given ID does not exist." }); } res.json(user); });
πΉ Best Practices:
β Always return a meaningful error message.
β Use the correct status code (400
, 404
, etc.).
β Include details about what went wrong.
π 3. Server Errors (5xx)
Server errors occur when something goes wrong on the backend.
Example: A database failure causes an API request to fail.
β Bad Example (No Error Handling)
app.get('/users', (req, res) => { throw new Error("Database failure"); // β This will crash the server });
β Good Example (Handling Server Errors)
app.get('/users', (req, res, next) => { try { throw new Error("Database failure"); // Simulated server error } catch (error) { next(error); // Pass error to global error handler } }); // Global Error Handler Middleware app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: "Internal Server Error", message: "Something went wrong on our end." }); });
πΉ Best Practices:
β Always catch unexpected errors.
β Use a global error handler to handle errors consistently.
β Never expose sensitive server details in error responses.
π 4. Structuring API Error Responses
A consistent error response format makes it easier for clients to handle errors.
β Example of a Good Error Response Format
{ "error": "Bad Request", "message": "Email is required", "statusCode": 400 }
β Example of a More Detailed Error Response
{ "error": "Validation Error", "message": "Invalid input data", "details": [ { "field": "email", "message": "Email is required" }, { "field": "password", "message": "Password must be at least 8 characters" } ], "statusCode": 400 }
π 5. Implementing a Global Error Handler in Express.js
Instead of handling errors individually, a global error handler ensures consistency.
π Example: Express.js Global Error Handler
const express = require('express'); const app = express(); app.use(express.json()); // Example Route with Error Handling app.get('/users/:id', (req, res, next) => { try { const user = null; // Simulating user not found if (!user) { throw { status: 404, message: "User not found" }; } res.json(user); } catch (error) { next(error); // Pass error to the error handler } }); // Global Error Handling Middleware app.use((err, req, res, next) => { res.status(err.status || 500).json({ error: err.status ? "Client Error" : "Server Error", message: err.message || "Something went wrong" }); }); app.listen(3033, () => console.log('Server running on port 3033'));
π― Summary
- Use the correct HTTP status codes to indicate the result of a request.
- Client errors (4xx) happen when requests are incorrect (e.g.,
404 Not Found
). - Server errors (5xx) happen when something goes wrong on the backend (e.g.,
500 Internal Server Error
). - Always return clear and structured error messages.
- Use a global error handler for better error management.
β Next Lesson: Introduction to CRUD Operations in REST APIs
In the next lesson, you'll learn how to perform CRUD (Create, Read, Update, Delete) operations using RESTful APIs. Youβll see how each HTTP method maps to a CRUD action! π