---
name: axios-401-interceptor-infinite-loop
description: Axios 401 response interceptor that calls the refresh endpoint must explicitly exclude that endpoint from retry — otherwise refresh failure triggers another refresh, infinite loop
type: concept
---

# Axios 401 Interceptor — Infinite Loop on Refresh Failure

## The Bug

A common pattern: intercept every 401 response → silently call `/api/auth/refresh` → retry original request.

**Problem:** if `/api/auth/refresh` itself returns 401 (expired refresh token, logged-out user), the interceptor catches *that* 401 and tries to refresh again → infinite loop.

```
GET /api/data → 401
  → POST /api/auth/refresh → 401  ← interceptor catches this too!
    → POST /api/auth/refresh → 401  ← infinite loop
```

## The Fix — Exclude the Refresh Endpoint

```ts
import axios from 'axios'

const api = axios.create({ baseURL: '/api' })

api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config

    // CRITICAL: skip refresh if this IS the refresh request
    if (
      error.response?.status === 401 &&
      !originalRequest._retry &&
      !originalRequest.url?.includes('/auth/refresh')  // ← guard
    ) {
      originalRequest._retry = true
      try {
        await api.post('/auth/refresh')
        return api(originalRequest)
      } catch {
        // Refresh failed — redirect to login
        window.location.href = '/login'
        return Promise.reject(error)
      }
    }

    return Promise.reject(error)
  }
)
```

## Key Details

| Guard | Purpose |
|-------|---------|
| `!originalRequest._retry` | Prevents retrying the same request twice |
| `!url.includes('/auth/refresh')` | Prevents the refresh call from re-triggering itself |

## Vue Router Integration

After failed refresh, use `router.push('/login')` instead of `window.location.href` to preserve SPA navigation:

```ts
import router from '@/router'

// inside the catch block:
await router.push('/login')
```

**Source:** daily/2026-05-13.md | 2026-05-13
