# Vue-Element-Admin request.js Axios Wrapper: Token Refresh Mechanism and 401 Error Handling

> Understand the vue-element-admin request.js Axios wrapper's approach to token refresh and 401 error handling. Learn how it manages expired tokens and login.

- Repository: [花裤衩/vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The [`request.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/request.js) wrapper in vue-element-admin does not implement automatic silent token refresh; instead, it detects expired tokens via custom backend response codes (50008, 50012, 50014) and forces a user re-login, while treating standard HTTP 401 errors as generic network failures.**

The [`request.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/request.js) file is the central HTTP client configuration in the PanJiaChen/vue-element-admin repository, providing a pre-configured Axios instance with interceptors for authentication and error handling. Understanding its token lifecycle is essential for developers customizing authentication flows or debugging session expiration issues.

## How request.js Injects Authentication Tokens

### Request Interceptor: Automatic Header Injection

Before any HTTP request leaves the application, the request interceptor in [`src/utils/request.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/request.js) (lines 13-24) checks the Vuex store for an existing session. If `store.getters.token` returns a value, the interceptor retrieves the actual token string via `getToken()` from [`src/utils/auth.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/auth.js) and injects it into the request headers as `X-Token`.

```javascript
// src/utils/request.js - Request interceptor
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers['X-Token'] = getToken()
    }
    return config
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

```

This ensures that authenticated routes receive the necessary credentials without manual header configuration in every API call.

## Business Logic Error Handling in Response Interceptors

### Custom Response Codes vs HTTP Status Codes

The wrapper differentiates between transport-layer failures (HTTP 4xx/5xx) and application-layer errors (custom JSON codes). In [`src/utils/request.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/request.js) (lines 45-68), the response interceptor examines the `code` field in the response body. While a successful response carries `code: 20000`, specific values trigger authentication-related actions:

- **50008**: Illegal token (tampered or malformed)
- **50012**: Other clients logged in (session concurrency)
- **50014**: Token expired

When these codes appear, the interceptor opens an Element-UI `MessageBox` dialog prompting the user to re-login:

```javascript
// Simplified excerpt from lines 45-68
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  MessageBox.confirm(
    'You have been logged out, you can cancel to stay on this page, or log in again',
    'Confirm logout',
    {
      confirmButtonText: 'Re-Login',
      cancelButtonText: 'Cancel',
      type: 'warning'
    }
  ).then(() => {
    store.dispatch('user/resetToken').then(() => {
      location.reload()  // Force reload to reset router and state
    })
  })
}

```

## The Absence of Silent Token Refresh

**No automatic token refresh mechanism exists** in the current implementation. Unlike modern OAuth2 clients that might call a `/refresh` endpoint upon detecting an expired access token, this wrapper immediately invalidates the session and requires manual user intervention.

The `resetToken` action in [`src/store/modules/user.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/store/modules/user.js) clears the Vuex state and removes the token from cookies/local storage, but it does not attempt to exchange a refresh token or negotiate a new session silently. This design assumes the backend uses short-lived tokens or session-based authentication where re-authentication is the preferred security posture.

## Handling HTTP 401 Unauthorized Errors

When the server returns a genuine HTTP 401 status (or any other non-2xx status) without the custom JSON body expected by the business logic interceptor, the error falls into the second response interceptor handler at lines 74-81:

```javascript
// src/utils/request.js - Error interceptor
service.interceptors.response.use(
  response => { /* ... success handling ... */ },
  error => {
    console.log('err' + error) // Debug logging
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

```

**Standard 401 errors are treated as generic network failures.** The interceptor displays the error message via Element-UI's `Message` component and propagates the rejected promise to the calling code. No automatic logout, token refresh, or redirection occurs for HTTP-level authentication failures.

## Practical Implementation Examples

### Making an Authenticated Request

API functions import the configured instance and benefit from automatic token injection:

```javascript
import request from '@/utils/request'

export function fetchUserProfile() {
  // X-Token header is injected automatically if user is logged in
  return request({
    url: '/user/profile',
    method: 'get'
  })
}

```

### Catching 401 Errors in Components

Since the wrapper rejects the promise for HTTP errors, components can handle authentication failures explicitly:

```javascript
export default {
  async created() {
    try {
      await this.$store.dispatch('user/getInfo')
    } catch (err) {
      // err.message contains the HTTP status text
      console.warn('Authentication failed:', err)
      this.$router.push('/login')
    }
  }
}

```

### Simulating Token Expiration Handling

When the backend returns `code: 50014`, the user sees a confirmation dialog. Upon confirmation, the application state resets:

```javascript
// This flow occurs automatically inside request.js when code === 50014
store.dispatch('user/resetToken').then(() => {
  // Clears localStorage/cookies and Vuex state
  location.reload() // Full page reload clears in-memory router state
})

```

## Summary

- **Automatic injection**: The request interceptor adds `X-Token` headers by reading from `store.getters.token` via `getToken()` in [`src/utils/auth.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/auth.js).
- **Custom code handling**: Responses with codes 50008, 50012, or 50014 trigger a logout dialog and dispatch `user/resetToken`, forcing re-authentication.
- **No silent refresh**: The wrapper does not implement refresh token logic; expired sessions always require user action.
- **HTTP 401 treatment**: Standard 401 responses surface as generic errors in the Axios error interceptor without automatic logout or token clearing.
- **State management**: Token removal occurs through [`src/store/modules/user.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/store/modules/user.js), ensuring both Vuex and persistent storage are cleared before reloading.

## Frequently Asked Questions

### How does request.js detect an expired token?

The wrapper checks the `code` field in JSON responses for specific values: **50014** (token expired), **50008** (illegal token), or **50012** (other clients logged in). When these appear, it displays a confirmation dialog and dispatches the `user/resetToken` action to clear the session. It does not inspect JWT expiration dates or attempt proactive validation.

### What is the difference between HTTP 401 and the custom 50014 code?

HTTP 401 is handled in the Axios error interceptor (lines 74-81) as a network-level failure, displaying a generic error message and rejecting the promise. The custom **50014** code is handled in the success interceptor (lines 45-68) as a business logic condition, triggering the logout/re-login flow. The application expects the backend to return 200 OK with a JSON body containing these custom codes rather than standard HTTP 401 statuses.

### Where is the authentication token stored in vue-element-admin?

The token is retrieved via `getToken()` from [`src/utils/auth.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/auth.js), which abstracts the storage mechanism (typically cookies or localStorage). The request interceptor accesses it through `store.getters.token` to check for existence, then reads the actual value via `getToken()` to inject into the `X-Token` header.

### Can I add automatic token refresh to request.js?

Yes, but it requires modifying [`src/utils/request.js`](https://github.com/PanJiaChen/vue-element-admin/blob/main/src/utils/request.js) to intercept 401 errors or specific custom codes, call a refresh endpoint, update the token via `setToken()`, and retry the original request. The current implementation deliberately avoids this pattern for simplicity, instead forcing a full page reload to clear all state when sessions expire.