Structured error handling with detailed error information, error codes, and type checking utilities for robust application error management.
Main error class extending native Error with detailed context about failed requests.
/**
* Axios-specific error with request/response context
*/
class AxiosError<T = unknown, D = any> extends Error {
constructor(
message?: string,
code?: string,
config?: InternalAxiosRequestConfig<D>,
request?: any,
response?: AxiosResponse<T, D>
);
/** Request configuration that caused the error */
config?: InternalAxiosRequestConfig<D>;
/** Error code string */
code?: string;
/** Request object (XMLHttpRequest, IncomingMessage, etc.) */
request?: any;
/** Response object if server responded */
response?: AxiosResponse<T, D>;
/** Always true for AxiosError instances */
isAxiosError: boolean;
/** HTTP status code if available */
status?: number;
/** Underlying error cause */
cause?: Error;
/** Serialize error to JSON object */
toJSON(): object;
}Usage Examples:
import axios from "axios";
try {
const response = await axios.get("https://api.example.com/users");
} catch (error) {
if (axios.isAxiosError(error)) {
console.log("Error message:", error.message);
console.log("Error code:", error.code);
console.log("Request URL:", error.config?.url);
console.log("HTTP status:", error.response?.status);
console.log("Response data:", error.response?.data);
// Serialize for logging
console.log("Full error:", error.toJSON());
}
}Predefined error codes for common failure scenarios.
// Network and connection errors
static readonly ERR_NETWORK = "ERR_NETWORK";
static readonly ECONNABORTED = "ECONNABORTED";
static readonly ETIMEDOUT = "ETIMEDOUT";
// Request/Response errors
static readonly ERR_BAD_REQUEST = "ERR_BAD_REQUEST";
static readonly ERR_BAD_RESPONSE = "ERR_BAD_RESPONSE";
// Configuration errors
static readonly ERR_BAD_OPTION = "ERR_BAD_OPTION";
static readonly ERR_BAD_OPTION_VALUE = "ERR_BAD_OPTION_VALUE";
// Feature/Support errors
static readonly ERR_NOT_SUPPORT = "ERR_NOT_SUPPORT";
static readonly ERR_DEPRECATED = "ERR_DEPRECATED";
// URL errors
static readonly ERR_INVALID_URL = "ERR_INVALID_URL";
// Cancellation errors
static readonly ERR_CANCELED = "ERR_CANCELED";
// Redirect errors
static readonly ERR_FR_TOO_MANY_REDIRECTS = "ERR_FR_TOO_MANY_REDIRECTS";Usage Examples:
try {
const response = await axios.get(url, { timeout: 5000 });
} catch (error) {
if (axios.isAxiosError(error)) {
switch (error.code) {
case axios.AxiosError.ETIMEDOUT:
console.log("Request timed out");
break;
case axios.AxiosError.ERR_NETWORK:
console.log("Network error occurred");
break;
case axios.AxiosError.ERR_BAD_REQUEST:
console.log("Bad request configuration");
break;
case axios.AxiosError.ERR_CANCELED:
console.log("Request was canceled");
break;
default:
console.log("Unknown error:", error.code);
}
}
}Create AxiosError instances from existing errors.
/**
* Create AxiosError from existing error
* @param error - Original error object
* @param code - Error code to assign
* @param config - Request configuration
* @param request - Request object
* @param response - Response object
* @param customProps - Additional properties
* @returns New AxiosError instance
*/
static AxiosError.from<T = unknown, D = any>(
error: Error | unknown,
code?: string,
config?: InternalAxiosRequestConfig<D>,
request?: any,
response?: AxiosResponse<T, D>,
customProps?: object
): AxiosError<T, D>;Usage Examples:
// Convert generic error to AxiosError
try {
// Some operation that might throw
throw new Error("Something went wrong");
} catch (originalError) {
const axiosError = axios.AxiosError.from(
originalError,
"CUSTOM_ERROR",
config,
request,
response,
{ customProperty: "additional context" }
);
throw axiosError;
}Specific error type for canceled requests.
/**
* Error thrown when request is canceled
*/
class CanceledError<T> extends AxiosError<T> {
constructor(message?: string, config?: InternalAxiosRequestConfig, request?: any);
}
// Legacy alias for backward compatibility
const Cancel = CanceledError;Utility functions to identify different types of errors.
/**
* Check if error is an AxiosError instance
* @param payload - Value to check
* @returns True if payload is AxiosError
*/
axios.isAxiosError<T = any, D = any>(payload: any): payload is AxiosError<T, D>;
/**
* Check if error is due to request cancellation
* @param value - Value to check
* @returns True if value represents cancellation
*/
axios.isCancel(value: any): value is Cancel;Usage Examples:
try {
const response = await axios.get(url);
} catch (error) {
if (axios.isCancel(error)) {
console.log("Request was canceled:", error.message);
return; // Handle cancellation gracefully
}
if (axios.isAxiosError(error)) {
// Handle different HTTP status codes
if (error.response) {
switch (error.response.status) {
case 400:
console.log("Bad request:", error.response.data);
break;
case 401:
console.log("Unauthorized - redirect to login");
window.location.href = "/login";
break;
case 403:
console.log("Forbidden - insufficient permissions");
break;
case 404:
console.log("Resource not found");
break;
case 429:
console.log("Rate limited - retry later");
break;
case 500:
case 502:
case 503:
case 504:
console.log("Server error - retry or show maintenance page");
break;
default:
console.log("HTTP error:", error.response.status);
}
} else if (error.request) {
console.log("No response received:", error.message);
} else {
console.log("Request setup error:", error.message);
}
} else {
console.log("Unknown error:", error);
}
}Structure of error responses when server returns an error.
interface AxiosResponse<T = any, D = any> {
/** Response data (error details from server) */
data: T;
/** HTTP status code */
status: number;
/** HTTP status message */
statusText: string;
/** Response headers */
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
/** Request configuration */
config: InternalAxiosRequestConfig<D>;
/** Native request object */
request?: any;
}Usage Examples:
try {
await axios.post("/api/users", userData);
} catch (error) {
if (axios.isAxiosError(error) && error.response) {
// Server responded with error status
const { status, data, headers } = error.response;
console.log("Status:", status);
console.log("Error data:", data);
// Handle API error responses
if (data.errors) {
// Validation errors
data.errors.forEach(err => {
console.log(`${err.field}: ${err.message}`);
});
} else if (data.message) {
// Simple error message
console.log("Error:", data.message);
}
// Check error-specific headers
const retryAfter = headers["retry-after"];
if (status === 429 && retryAfter) {
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
}
}
}Common patterns for handling errors application-wide.
Usage Examples:
// Global error interceptor
axios.interceptors.response.use(
(response) => response,
(error) => {
if (axios.isAxiosError(error)) {
// Log all axios errors
console.error("Axios Error:", {
url: error.config?.url,
method: error.config?.method,
status: error.response?.status,
message: error.message,
data: error.response?.data
});
// Handle specific error cases
if (error.response?.status === 401) {
// Redirect to login
localStorage.removeItem("authToken");
window.location.href = "/login";
return Promise.reject(error);
}
if (error.response?.status >= 500) {
// Show generic server error message
showNotification("Server error occurred. Please try again later.", "error");
}
}
return Promise.reject(error);
}
);
// Error boundary for React applications
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
if (axios.isAxiosError(error)) {
// Send axios errors to monitoring service
sendToMonitoring({
type: "axios_error",
url: error.config?.url,
status: error.response?.status,
message: error.message,
stack: error.stack
});
}
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
// Retry with exponential backoff
async function retryRequest(requestFn, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await requestFn();
} catch (error) {
if (axios.isAxiosError(error)) {
const shouldRetry = error.response?.status >= 500 ||
error.code === "ECONNABORTED" ||
error.code === "ERR_NETWORK";
if (shouldRetry && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
console.log(`Request failed, retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
throw error; // Re-throw if not retryable or max retries reached
}
}
}
// Usage
try {
const response = await retryRequest(() =>
axios.get("https://unreliable-api.example.com/data")
);
console.log(response.data);
} catch (error) {
console.log("Request failed after retries:", error.message);
}Extend AxiosError for application-specific error handling.
Usage Examples:
// Custom error for API validation errors
class ValidationError extends axios.AxiosError {
constructor(errors, config, request, response) {
super("Validation failed", "VALIDATION_ERROR", config, request, response);
this.name = "ValidationError";
this.validationErrors = errors;
}
getFieldErrors() {
return this.validationErrors || [];
}
}
// Custom error for business logic errors
class BusinessLogicError extends axios.AxiosError {
constructor(businessCode, message, config, request, response) {
super(message, "BUSINESS_ERROR", config, request, response);
this.name = "BusinessLogicError";
this.businessCode = businessCode;
}
}
// Error factory
function createAppError(axiosError) {
if (axiosError.response?.status === 422) {
return new ValidationError(
axiosError.response.data.errors,
axiosError.config,
axiosError.request,
axiosError.response
);
}
if (axiosError.response?.data?.businessCode) {
return new BusinessLogicError(
axiosError.response.data.businessCode,
axiosError.response.data.message,
axiosError.config,
axiosError.request,
axiosError.response
);
}
return axiosError; // Return original error
}
// Usage in interceptor
axios.interceptors.response.use(
(response) => response,
(error) => {
if (axios.isAxiosError(error)) {
throw createAppError(error);
}
throw error;
}
);