← Back to list

Senior-Level Error Handling with Axios in React

Overview

Abdullah Alnoime · 2026-05-16 14:59 · 8 claps · 3.2 min read
#axios #error-handling #react #interceptors #frontend
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Senior-Level Error Handling with Axios in React

Overview

Error handling is not an afterthought in mature React applications. Senior engineers treat it as a first-class architectural concern because it directly affects:

  • User experience and trust.
  • Application stability.
  • Debugging speed.
  • Security and authentication flows.

This document presents a production-ready, senior-level approach to handling errors with Axios in React. The strategy is based on four core principles:

  1. Centralize error handling.
  2. Classify errors explicitly.
  3. Retry intelligently.
  4. Fail gracefully and observably.

Centralize error handling with Axios interceptors

Why centralization matters ?!

Junior implementations often rely on repeating try/catch blocks for every API call. This leads to:

  • Inconsistent error behavior.
  • Duplicated logic.
  • Missed edge cases (such as expired authentication tokens).

Senior engineers instead centralize cross-cutting concerns — like authentication failures — using Axios interceptors.

Core idea

  • Let Axios handle global concerns (authentication, redirection, token refresh).
  • Let components focus on UI-level concerns only.

Axios instance with global error interceptor

import axios from "axios";

const api = axios.create({
  baseURL: "https://example.com",
  timeout: 10000,
});

api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const status = error.response?.status;
    // Global authentication handling
    if (status === 401) {
      console.warn("Token expired. Redirecting to login.");
      window.location.href = "/login";
      return;
    }
    // Forward all other errors to the caller
    return Promise.reject(error);
  }
);

export default api;

What this achieves

  • Authentication failures are handled once.
  • All API consumers behave consistently.
  • UI components remain clean and predictable.

Classify errors explicitly at the component level

Why error classification is critical ?!

Not all errors are equal. A senior developer never shows the same message for:

  • A server validation error.
  • A lost internet connection.
  • A broken request configuration.

Axios provides enough information to distinguish these cases clearly.

Axios error categories

Axios errors fall into three deterministic types:

  1. Response Error: The server responded with a non-2xx status code.
  2. Network Error: The request was sent, but no response was received.
  3. Setup Error: The request failed before being sent (configuration or runtime issue).

Reusable error normalization function

Senior teams often standardize this logic into a single helper.

export function handleApiError(error: any): string {
  if (error.response) {
    // Server responded with an error status
    return `Error ${error.response.status}: ${
      error.response.data?.message || "Unexpected server error"
    }`;
  }
  if (error.request) {
    // Request made but no response received
    return "Network error. Please check your internet connection.";
  }
  // Something went wrong while setting up the request
  return "An unexpected error occurred while preparing the request.";
}

This function becomes a contract so every API consumer receives a predictable message.

Component-Level usage with clear responsibilities

Example: Fetching a user profile

import { useState } from "react";
import api from "@/lib/api";
import { handleApiError } from "@/utils/handleApiError";

const UserProfile = () => {
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  const fetchUser = async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await api.get("/api/user");
      // Process response data here
    } catch (err) {
      setError(handleApiError(err));
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <button onClick={fetchUser} disabled={loading}>
        Load Profile
      </button>
      {error && <p role="alert">{error}</p>}
    </>
  );
};

export default UserProfile;

Architectural responsibility separation

The system is designed with clear ownership at each layer. Cross-cutting concerns like authentication and redirects are handled centrally, while error handling is normalized and managed consistently. UI components focus only on rendering predictable states, with recovery actions handled in well-defined boundaries.

This level of separation reflects a mature, senior-level architectural approach.

Automated retries for unstable networks

Why retries should be selective ?!

Retrying every failed request is dangerous. Senior engineers retry only when:

  • The error is network-related.
  • The request is idempotent (e.g., GET).
  • The retry count is limited.

Using axios-retry with exponential backoff

import axios from "axios";
import axiosRetry from "axios-retry";

axiosRetry(api, {
  retries: 3,
  retryDelay: axiosRetry.exponentialDelay,
  retryCondition: (error) =>
    axiosRetry.isNetworkError(error) ||
    axiosRetry.isRetryableError(error),
});

Benefits

  • Reduces false error messages.
  • Improves perceived reliability.
  • Protects backend services from retry storms.

Graceful recovery and user control

A Senior Rule

Errors should never trap the user. Every recoverable error must provide a clear next action.

Example: Retry UI pattern

{error && (
  <div>
    <p>{error}</p>
    <button onClick={fetchUser}>Try Again</button>
  </div>
)}

This approach respects user agency and reduces frustration.

Structured logging for debugging and monitoring

Why logging matters ?!

User-facing messages should be friendly. Logs should be detailed.

Axios provides structured error data that is safe to serialize.

catch (error) {
  console.error("API Error:", error.toJSON());
  setError(handleApiError(error));
}

What this enables

  • Faster debugging.
  • Better observability.
  • Easier integration with monitoring tools.

Final Architectural Summary

Senior-level Axios error handling is defined by clarity, consistency, and intent.

  • Centralize what must be global.
  • Classify errors deterministically.
  • Retry only when it makes sense.
  • Always provide recovery paths.
  • Log for developers, not users.

When implemented correctly, error handling becomes invisible to users but invaluable to all dev teams.


메타데이터
post_id
efb2d893358b
slug
senior-level-error-handling-with-axios-in-react-efb2d893358b
url
https://medium.com/@abdullahalnoime/senior-level-error-handling-with-axios-in-react-efb2d893358b
canonical_url
https://medium.com/@abdullahalnoime/senior-level-error-handling-with-axios-in-react-efb2d893358b
author_url
https://medium.com/@abdullahalnoime
status
ok
fetched_at
2026-06-22 12:55:45