Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

3d8872f30f6d29f809fdd78fc4512ca0's avatar

Intermittent 419 error for some users when POSTing with Axios

I'm using Vue and Axios on the front-end. Some users' POST requests are failing with a 419 error. I'm using TrackJS to monitor console errors on the users' side and I can see it's happening to roughly 1 in 50 users.

Here is the error log:

Severity:
LOG
Message:
{
  "data": {
    "message": ""
  },
  "status": 419,
  "statusText": "unknown status",
  "headers": {
    "date": "Mon, 17 Sep 2018 21:48:21 GMT",
    "cache-control": "no-cache, private",
    "server": "nginx/1.10.3 (Ubuntu)",
    "connection": "keep-alive",
    "transfer-encoding": "chunked",
    "content-type": "application/json"
  },
  "config": {
    "transformRequest": {},
    "transformResponse": {},
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1,
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "X-Requested-With": "XMLHttpRequest",
      "X-CSRF-TOKEN": "4EcoKUTAtwu5VR3vcxQZoFktgQTAgy0ctfHCbUdP",
      "Content-Type": "application/json;charset=utf-8"
    },
    "method": "post",
    "url": "/category/",
    "data": "{\"slug\":\"\"}"
  },
  "request": {
    "_trackJs": {
      "method": "POST",
      "url": "/category/",
      "logId": "5f3fd3c1-6677-4e12-a658-9b40e317e9f0"
    }
  }
}

On my page, I've got the csrf-token set in the meta tag in the page head like so: <meta name="csrf-token" content="{{ csrf_token() }}"> And of course, I'm registering the CSRF Token as a common header with Axios like so:

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

The error log on failed requests is showing that the X-CSRF-TOKEN is present in the header.

At first I was using Cloudflare's CDN, however I've temporarily disabled it in case it was inadvertently hiding session data from some clients.

In config/session.php, my session lifetime is still set to the default 120 minutes, and expire_on_close is false.

Many other 'solutions' for this error recommend excluding the error-prone routes from CSRF verification by adding them to the $except array, moving them to an API route, or switching them to GETs. I require CSRF, so these solutions are not acceptable.

Does anyone have any other suggestions or ideas for further testing/experimentation?

0 likes
5 replies
3d8872f30f6d29f809fdd78fc4512ca0's avatar

About 1 in 50 users are having the issue. I've found the Session Sweeping Lottery in config/session.php, it's set to the default value of [2, 100]. Perhaps that has something to do with it.

D9705996's avatar

A 419 error is caused by an expired CSRF token. If your using an SPA this will happen after your users session expires.

If you cannot use API routes which is the recommended method you will need to add code to your axios error handler to do a new GET request to obtain a valid CSRF token then retry your original request. I believe axios interceptors are what your looking for

https://github.com/axios/axios#interceptors

3d8872f30f6d29f809fdd78fc4512ca0's avatar

Thanks very much for your excellent suggestion. The solution mentioned in the Medium article you linked worked with a bit of refactoring. I've run a few tests and the SPA is now reloading the CSRF token, 'silently,' and running the request again.

For any desperate Googlers who just want a quick fix at the cost of UX, the article mentions using an axios interceptor that reloads the page if a response comes back with a 419.

axios.interceptors.response.use(function(response){
    return response;
}, function(error){
    if(error.response.status !== 419) return Promise.reject(error);
    window.location.reload();
});

Your user(s) may lose unsaved form data, however.

Stormix's avatar

For any desperate Googlers, still looking for a solution to this issue, I wrote a "detailed" tutorial on how to solve it using Axios interceptors to silently update the CSRF token.

https://blog.anasmazouni.dev/solving-laravel-vue-spa-419-token-mismatch/

It's inspired by the Medium article but provides an easier solution that doesn't require a whole wrapper around axios and that is typescript friendly.

Please or to participate in this conversation.