JAVASCRIPT

Centralized API Error Handling and Logging in Node.js

Implement a robust, centralized error handling and logging mechanism for external API calls in a Node.js application to improve debugging and reliability.

const axios = require('axios');

class ApiError extends Error {
    constructor(message, statusCode = 500, details = {}) {
        super(message);
        this.name = 'ApiError';
        this.statusCode = statusCode;
        this.details = details;
        Error.captureStackTrace(this, this.constructor);
    }
}

// A simple logger for demonstration
const logger = {
    error: (message, context) => console.error(`[ERROR] ${message}`, context),
    warn: (message, context) => console.warn(`[WARN] ${message}`, context),
    info: (message, context) => console.log(`[INFO] ${message}`, context)
};

async function makeApiCall(config) {
    try {
        const response = await axios(config);
        return response.data;
    } catch (error) {
        if (axios.isAxiosError(error)) {
            const { response } = error;
            const statusCode = response ? response.status : 500;
            const errorMessage = response ? (response.data.message || response.statusText) : error.message;
            const errorDetails = response ? response.data : null;

            logger.error(`API Call Failed: [${statusCode}] ${errorMessage}`, { 
                url: config.url, 
                method: config.method, 
                errorDetails 
            });
            throw new ApiError(errorMessage, statusCode, errorDetails);
        } else {
            // Non-Axios errors (e.g., network issues before request sent)
            logger.error(`General API Call Error: ${error.message}`, { url: config.url, method: config.method, originalError: error });
            throw new ApiError('An unexpected error occurred during the API call.', 500, { originalError: error });
        }
    }
}

// Example Usage:
// (async () => {
//     try {
//         const data = await makeApiCall({
//             method: 'GET',
//             url: 'https://jsonplaceholder.typicode.com/posts/1'
//         });
//         logger.info('Successfully fetched data:', data);

//         // Example of an API call that will fail
//         await makeApiCall({
//             method: 'GET',
//             url: 'https://jsonplaceholder.typicode.com/nonexistent-endpoint'
//         });
//     } catch (e) {
//         if (e instanceof ApiError) {
//             logger.warn(`Caught custom ApiError: ${e.message} (Status: ${e.statusCode})`);
//         } else {
//             logger.error(`Caught unexpected error: ${e.message}`);
//         }
//     }
// })();
How it works: This Node.js snippet establishes a centralized mechanism for handling and logging errors from external API calls using Axios. It introduces a custom `ApiError` class to encapsulate relevant error details like status code and original API response. The `makeApiCall` wrapper intelligently distinguishes between Axios-specific errors (HTTP responses) and general network issues. All errors are logged with contextual information (URL, method, error details) before being re-thrown as instances of `ApiError`. This pattern makes error identification, debugging, and consistent error messaging throughout your application much easier.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs