https://axios.nuxtjs.org/extend
Follow setting axios from nuxt documentary.
Whenever we catch the error inside $axios.onError we should redirect to the given route. I could handle the error on each request by catching it, but as far as we got global handler we should be able to catch it in one place.
It is throwing NuxtServerError.
[Axios] Response error: Request failed with status code 401
09:59:32
at createError (node_modules/axios/lib/core/createError.js:16:15)
at settle (node_modules/axios/lib/core/settle.js:18:12)
at IncomingMessage.handleStreamEnd (node_modules/axios/lib/adapters/http.js:201:11)
at IncomingMessage.emit (events.js:202:15)
at IncomingMessage.EventEmitter.emit (domain.js:481:20)
at endReadableNT (_stream_readable.js:1132:12)
at processTicksAndRejections (internal/process/next_tick.js:76:17)
I would like to add my code to describe more precisely situation:
I have registered axios module and extended it:
plugins: [
'~plugins/axios',
],
modules: [
'@nuxtjs/axios',
],
The plugin:
const EXPIRED_TOKEN_MESSAGE = 'Expired JWT Token';
export default function ({
$axios, redirect, app, store,
}) {
$axios.setHeader('Content-Type', 'application/json');
$axios.setHeader('Accept', 'application/json');
$axios.onRequest((config) => {
console.log(`Making request to ${config.url}`);
});
$axios.onError((error) => {
const { response: { data: { message } } } = error;
if (message === EXPIRED_TOKEN_MESSAGE) {
store.dispatch('authentication/logout');
}
store.dispatch('alerts/addAlert', { type: 'error', message });
});
}
The store:
logout({ commit }) {
Cookie.remove('jwt');
commit('setUser', null);
commit('data/clearStorage', {}, { root: true });
this.$router.push({ name: 'index' });
},
Hi. You have to handle the error. Maybe returning an empty object at the end of onError handler.
@pi0 Hello, thank you for fast response. Even when you return Promise.reject(error); it will not work. Could we get update of the docs in extending axios section with working example when the error occurs on the server side ?
It works as expected. Promise.reject means also throwing an error (promise chain).
$axios.onError((error) => {
const { response: { data: { message } } } = error;
if (message === EXPIRED_TOKEN_MESSAGE) {
store.dispatch('authentication/logout');
}
store.dispatch('alerts/addAlert', { type: 'error', message });
return false
});
As this is a global handler, you have to check response when using.
async asyncData({ $axios }) {
const res = $axios.$get('...')
if (!res) {
// An error occured
}
}
Thank you for explanation, I though that you could handle everything in global handler as the name is pointing 'onError'.
True. But the result of $get/get function should be finally an error or some value. Not returning or returning undefined from interceptor means we just intercepted error for example for logging stuff.
I did as you say. Update slightly my code by adding catch(e => console.log(e)) to the request and next error occurred in node_modules/@nuxt/devalue/dist/devalue.cjs.js
RangeError
Maximum call stack size exceeded
You are returning entire error object in asyncData result. Can you please share full code of asyncData and newly changed onError?
I found what is the problem: nuxtServerInit is running into infinity loop. I do have authentication copy pasted from Nuxt guide the only thing I have added is Axios interceptor helpers based on newest approach.
Axios.js plugin:
const EXPIRED_TOKEN_MESSAGE = 'Expired JWT Token';
export default function ({
$axios, redirect, app, store,
}) {
$axios.setHeader('Content-Type', 'application/json');
$axios.setHeader('Accept', 'application/json');
$axios.onRequest((config) => {
config.headers.JWTAuthorization = `Bearer ${store.state.authentication.jwt}`;
});
$axios.onError((error) => {
const { response: { data: { message } } } = error;
if (message === EXPIRED_TOKEN_MESSAGE) {
store.dispatch('authentication/logout');
$axios.defaults.headers.common.JWTAuthorization = null;
}
store.dispatch('alerts/addAlert', { type: 'error', message });
return Promise.reject(error.response);
});
}
Vuex store authentication actions:
export default {
async authenticateUser({ commit, dispatch }, { data }) {
await this.app.$axios.$post('login', data).then(({ token }) => {
this.app.$axios.setHeader('JWTAuthorization', `Bearer ${token}`);
Cookie.set('jwt', token);
commit('setAction', { key: 'jwt', value: token });
dispatch('getUser');
}).catch(e => console.log(e));
},
async getUser({ commit }) {
await this.app.$axios.$get('profile').then((user) => {
commit('setAction', { key: 'user', value: user });
this.$router.push({ name: 'dashboard' });
}).catch(e => console.log(e));
},
logout({ commit }) {
Cookie.remove('jwt');
commit('setAction', { key: 'user', value: null });
commit('setAction', { key: 'jwt', value: null });
commit('data/clearStorage', {}, { root: true });
},
};
Vuex store authentication state:
const state = () => ({
user: null,
jwt: null,
});
export default state;
And the two middleware:
authenticated.js added into default layout
export default async function ({ store, redirect }) {
if (!store.state.authentication.user) {
await store.dispatch('authentication/getUser');
}
if (!store.state.authentication.jwt) {
return redirect('/');
}
}
notAuthenticated added into login layout
export default function ({ store, redirect }) {
if (store.state.authentication.jwt) {
return redirect('/dashboard');
}
}
Expected action:
When the axios onError interceptor is hit it should logout user.
What is happening:
nuxtServerInit is keep running at the infinity loop - even when cookies are removed, the seems to be passed into req.headers.cookie.
Any approach for my case ? I would be grateful @pi0
It is only occurring at the server side when page is refreshed and token invalidated - when we are in the app, after token invalidates the behaviour is correct.
@derpdead - did you find a good solution for this? I'm experiencing similar behaviour.
✔ Server
Compiled successfully in 15.07s
ℹ Waiting for file changes 17:33:36
READY Server listening on http://localhost:3000 17:33:36
(node:3861) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
at createError (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/core/createError.js:16:15)
at settle (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/adapters/http.js:237:11)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
(node:3861) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:3861) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:3861) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
at createError (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/core/createError.js:16:15)
at settle (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/home/kus3/Desktop/Heroku/nuxt-auth-kus/node_modules/axios/lib/adapters/http.js:237:11)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
(node:3861) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)
/--------------------------------------------------------------------------------------------------------/
every thing is fine .and project is running but still
this error is coming in console in nuxt js
I have the same

I find a way to disable nuxt interceptors
Works with
$axios.onError((error) => {
// store.dispatch...
return true
})
but it maybe breaks @nuxtjs/auth
I find it tedious to have a .catch(console.log) after each request. I do even more every time a request fails. But I still get sent to the error page of Axios. Is there any way to prevent this?
I tried the return true or return false at the end of my onError interceptor.
This is what my interceptor looks like
$axios.onError(error => {
const code = parseInt(error.response && error.response.status)
if (code === 401 || code === 403) {
store.dispatch('logout')
} else {
store.dispatch('snackbar/error')
}
})
While it is not really recommended to globally suppress errors what you can do is:
export default function ({ $axios }) {
$axios.onError((error) => {
return { error, data: {} }
})
}
It will cause if $axios requests failing, return an empty object for data and error is available in reponse object but nothing throws anymore.
Sorry for bumping a closed issue, but I'm seeing similar issues and I'd really like to understand how things are supposed to work.
I prepared a CodeSandbox, I hope @pi0 you are able to have a look: https://codesandbox.io/s/floral-voice-flh6f?file=/pages/fail.vue. It uses a plugin $apiClient to handle api calls with Axios, the structure of which is based on this post: Organize and decouple your API calls in Nuxt.js. This plugin also adds error handling using the onError interceptor. Two pages (working.vue and fail.vue) use this apiClient to retrieve data. One works but the other uses an incorrect id on purpose, causing a 404 response from the api server. I expect this error to be handled by the onError hook.
Now my question... The only way I was able to get the error handling to work, was by adding .catch() in my asyncData hook like this:
asyncData({ $apiClient }) {
return $apiClient.mountains
.get("aconcagua")
.then((response) => {
return { response };
})
.catch(() => false);
},
As you can see the .catch(() => false); line doesn't do much, but without it, the Axios error handler doesn't kick in. Is this how it's supposed to be? How does this work? Shouldn't the onError interceptor take simply care of things, regardless of what happens in asyncData?
Thank you for your time and support.
Hi @marcvangend It is because you need to resolve response in error interceptor otherwise it will be simply just intercepted (for logging or show an alert). So this fixes issue: (sandbox)
client.onError((err) => {
return Promise.resolve(false); <--
});
If you wish to update docs noticing this, would be awesome :)
Ah, excellent, thank you @pi0! At least it's reassuring to see that I was pretty close :-)
So if I understand correctly:
error() function earlier. (That last bit it what caused my confusion, I guess.)I will try to submit a PR for the docs.
i solved this problem with error catcher in fetch request
async fetch() {
try {
await this.getLogs()
} catch (error) {
if (process.server) {
const code = this.$nuxt.context.res.statusCode
if (code === 401) {
this.$store.dispatch('auth/logout')
}
}
}
},
Most helpful comment
While it is not really recommended to globally suppress errors what you can do is:
It will cause if
$axiosrequests failing, return an empty object for data anderroris available in reponse object but nothing throws anymore.