Skip to main content

Overview

Axios 1.x introduced several breaking changes to improve consistency, security, and developer experience. This guide helps you upgrade from Axios 0.x to 1.x by documenting breaking changes and providing migration strategies.
Migration timeline: Simple applications take 1-2 hours, medium applications 1-2 days, and large applications with complex error handling 3-5 days.

Key changes summary

Area0.x Behavior1.x BehaviorImpact
Error handlingSelective throwingConsistent throwingHigh
JSON parsingLenientStrictMedium
Browser supportIE11+Modern browsersLow-Medium
TypeScriptPartialFull supportLow

Breaking changes

Error handling changes

The most significant change in Axios 1.x is how errors are handled.
// Axios 0.x - Some HTTP error codes didn't throw
axios.get('/api/data')
  .then(response => {
    console.log('Success:', response.data);
  });

// Response interceptor could "swallow" errors
axios.interceptors.response.use(
  response => response,
  error => {
    handleError(error);
    // Error was "handled" and didn't propagate
  }
);
Response interceptors can no longer “swallow” errors silently. Every API call must handle errors explicitly or they become unhandled promise rejections.

JSON parsing changes

// Lenient JSON parsing - would attempt to parse invalid JSON
response.data; // Might contain partial data or fallbacks

Transform changes

// Axios 1.x - Headers parameter always available
transformRequest: [function (data, headers) {
  // More predictable behavior
  return data;
}]

Browser support changes

  • 0.x: Supported IE11 and older browsers
  • 1.x: Requires modern browsers with Promise support
  • Polyfills: May be needed for older browser support

Migration strategies

Strategy 1: Centralized error handling

class ApiErrorHandler {
  constructor() {
    this.setupInterceptors();
  }

  setupInterceptors() {
    axios.interceptors.response.use(
      response => response,
      error => {
        this.processError(error);
        
        // Return resolved promise for handled errors
        if (this.isHandledError(error)) {
          return Promise.resolve({
            data: null,
            error: this.normalizeError(error),
            handled: true
          });
        }
        
        return Promise.reject(error);
      }
    );
  }

  processError(error) {
    console.error('API Error:', error);
    
    if (error.response?.status === 401) {
      this.handleAuthError();
    } else if (error.response?.status >= 500) {
      this.showErrorNotification('Server error occurred');
    }
  }

  isHandledError(error) {
    const handledStatuses = [401, 403, 404, 422, 500, 502, 503];
    return handledStatuses.includes(error.response?.status);
  }

  normalizeError(error) {
    return {
      status: error.response?.status,
      message: error.response?.data?.message || error.message,
      code: error.response?.data?.code || error.code
    };
  }
}

const errorHandler = new ApiErrorHandler();

Strategy 2: Wrapper function pattern

function createSafeApi() {
  const api = axios.create();
  
  api.interceptors.response.use(
    response => ({ data: response.data, error: null }),
    error => {
      return Promise.resolve({
        data: null,
        error: {
          status: error.response?.status,
          message: error.response?.data?.message || error.message
        }
      });
    }
  );
  
  return api;
}

const api = createSafeApi();

// Usage - always returns a resolved promise
const { data, error } = await api.get('/api/users');
if (error) {
  console.error('Request failed:', error);
} else {
  console.log('Success:', data);
}

Strategy 3: Gradual migration with adapter

// Create instances for gradual migration
const legacyApi = axios.create({
  // Keep old behavior for legacy code
  validateStatus: () => true
});

const modernApi = axios.create({
  // Use new 1.x behavior for new code
});

// Migrate endpoints one at a time
const userService = {
  getUsers: () => modernApi.get('/api/users'),
  getLegacyData: () => legacyApi.get('/api/legacy')
};

Common patterns

Updating async/await code

async function fetchUser(id) {
  const response = await axios.get(`/api/users/${id}`);
  return response.data;
}

Updating promise chains

axios.get('/api/data')
  .then(response => {
    processData(response.data);
  });

Updating global interceptors

// Add proper error handling in interceptors
axios.interceptors.response.use(
  response => response,
  async error => {
    // Handle token refresh
    if (error.response?.status === 401) {
      try {
        await refreshToken();
        return axios.request(error.config);
      } catch (refreshError) {
        return Promise.reject(refreshError);
      }
    }
    
    // Always return rejected promise for unhandled errors
    return Promise.reject(error);
  }
);

Testing your migration

1

Update Axios

npm install axios@latest
2

Add error handling

Update all axios calls to include .catch() or try/catch blocks
3

Test error scenarios

  • Test 4xx responses (client errors)
  • Test 5xx responses (server errors)
  • Test network failures
  • Test timeout scenarios
4

Update interceptors

Ensure all interceptors properly propagate errors
5

Run integration tests

Verify all API calls work as expected

Troubleshooting

This is the most common issue. Add .catch() handlers or try/catch blocks to all axios calls.
// Before
axios.get('/api/data').then(r => console.log(r.data));

// After
axios.get('/api/data')
  .then(r => console.log(r.data))
  .catch(e => console.error(e));
Ensure interceptors return Promise.reject(error) to propagate errors:
axios.interceptors.response.use(
  response => response,
  error => {
    handleError(error);
    return Promise.reject(error); // Must return rejected promise
  }
);
Axios 1.x is stricter about JSON parsing. Use transformResponse for custom parsing:
axios.get('/api/data', {
  transformResponse: [function (data) {
    try {
      return JSON.parse(data);
    } catch (e) {
      return data; // Return raw data on parse error
    }
  }]
});

Resources

Axios 1.x Changelog

Complete list of changes in version 1.x

Error handling guide

Comprehensive error handling documentation

Build docs developers (and LLMs) love