How to catch and handle error response 422 with Redux/Axios?

JavascriptReactjsReduxAxios

Javascript Problem Overview


I have an action making a POST request to the server in order to update a user's password, but I'm unable to handle the error in the chained catch block.

return axios({
  method: 'post',
  data: {
    password: currentPassword,
    new_password: newPassword
  },
  url: `path/to/endpoint`
})
.then(response => {
  dispatch(PasswordUpdateSuccess(response))
})
.catch(error => {
  console.log('ERROR', error)
  switch (error.type) {
    case 'password_invalid':
      dispatch(PasswordUpdateFailure('Incorrect current password'))
      break
    case 'invalid_attributes':
      dispatch(PasswordUpdateFailure('Fields must not be blank'))
      break
  }
})

When I log the error this is what I see:

Error Logged

When I check the network tab I can see the response body, but for some reason I can't access the values!

Network Tab

Have I unknowingly made a mistake somewhere? Because I'm handling other errors from different request fine, but can't seem to work this one out.

Javascript Solutions


Solution 1 - Javascript

Example

getUserList() {
    return axios.get('/users')
      .then(response => response.data)
      .catch(error => {
        if (error.response) {
          console.log(error.response);
        }
      });
  }

Check the error object for response, it will include the object you're looking for so you can do error.response.status

enter image description here

https://github.com/mzabriskie/axios#handling-errors

Solution 2 - Javascript

Axios is probably parsing the response. I access the error like this in my code:

axios({
  method: 'post',
  responseType: 'json',
  url: `${SERVER_URL}/token`,
  data: {
    idToken,
    userEmail
  }
})
 .then(response => {
   dispatch(something(response));
 })
 .catch(error => {
   dispatch({ type: AUTH_FAILED });
   dispatch({ type: ERROR, payload: error.data.error.message });
 });

From the docs:

The response for a request contains the following information.

{
  // `data` is the response that was provided by the server
  data: {},

  // `status` is the HTTP status code from the server response
  status: 200,

  // `statusText` is the HTTP status message from the server response
  statusText: 'OK',

  // `headers` the headers that the server responded with
  headers: {},

  // `config` is the config that was provided to `axios` for the request
  config: {}
}

So the catch(error => ) is actually just catch(response => )

EDIT:

I still dont understand why logging the error returns that stack message. I tried logging it like this. And then you can actually see that it is an object.

console.log('errorType', typeof error);
console.log('error', Object.assign({}, error));

EDIT2:

After some more looking around this is what you are trying to print. Which is a Javascipt error object. Axios then enhances this error with the config, code and reponse like this.

console.log('error', error);
console.log('errorType', typeof error);
console.log('error', Object.assign({}, error));
console.log('getOwnPropertyNames', Object.getOwnPropertyNames(error));
console.log('stackProperty', Object.getOwnPropertyDescriptor(error, 'stack'));
console.log('messageProperty', Object.getOwnPropertyDescriptor(error, 'message'));
console.log('stackEnumerable', error.propertyIsEnumerable('stack'));
console.log('messageEnumerable', error.propertyIsEnumerable('message'));

Solution 3 - Javascript

Here is the proper way to handle the error object:

axios.put(this.apiBaseEndpoint + '/' + id, input)
.then((response) => {
    // Success
})
.catch((error) => {
    // Error
    if (error.response) {
        // The request was made and the server responded with a status code
        // that falls out of the range of 2xx
        // console.log(error.response.data);
        // console.log(error.response.status);
        // console.log(error.response.headers);
    } else if (error.request) {
        // The request was made but no response was received
        // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
        // http.ClientRequest in node.js
        console.log(error.request);
    } else {
        // Something happened in setting up the request that triggered an Error
        console.log('Error', error.message);
    }
    console.log(error.config);
});

Origin url https://gist.github.com/fgilio/230ccd514e9381fafa51608fcf137253

Solution 4 - Javascript

axios.post('http://localhost:8000/api/auth/register', {
    username : 'test'
}).then(result => {
    console.log(result.data)
}).catch(err => {
    console.log(err.response.data)
})

add in catch geting error response ==> err.response.data

Solution 5 - Javascript

I was also stumped on this for a while. I won't rehash things too much, but I thought it would be helpful to others to add my 2 cents.

The error in the code above is of type Error. What happens is the toString method is called on the error object because you are trying to print something to the console. This is implicit, a result of writing to the console. If you look at the code of toString on the error object.

Error.prototype.toString = function() {
  'use strict';

  var obj = Object(this);
  if (obj !== this) {
    throw new TypeError();
  }

  var name = this.name;
  name = (name === undefined) ? 'Error' : String(name);

  var msg = this.message;
  msg = (msg === undefined) ? '' : String(msg);

  if (name === '') {
    return msg;
  }
  if (msg === '') {
    return name;
  }

  return name + ': ' + msg;
};

So you can see above it uses the internals to build up the string to output to the console.

There are great docs on this on mozilla.

Solution 6 - Javascript

You can use inline if else statement like so:

.catch(error => {
	dispatch({
		type: authActions.AUTH_PROCESS_ERROR,
		error: error.response ? error.response.data.code.toString() : 'Something went wrong, please try again.'
	}); 
});

Solution 7 - Javascript

The only thing what helped me was the following:

axios.put('/api/settings', settings, {
  validateStatus: status => status >= 200 && status < 300 || status === 422
})

https://stackoverflow.com/a/66285529/5849569

Solution 8 - Javascript

I recommend handling errors via Axios interceptors, individually for each case scenario:

// interceptor to catch errors
const errorInterceptor = (error) => {
  // check if it's a server error
  if (!error.response) {
    console.log('📡 API | Network/Server error')
    return Promise.reject(error)
  }

  // all the error responses
  switch (error.response.status) {
    case 400:
      console.error(error.response.status, error.message)
      console.log('📡 API | Nothing to display', 'Data Not Found')
      break

    case 401: // authentication error, logout the user
      console.log('📡 API | Please login again', 'Session Expired')
      localStorage.removeItem('user')
      break

    case 403:
      console.error(error.response.status, error.message)
      console.log('📡 API | Access denied', 'Data Not Found')
      break

    case 404:
      console.error(error.response.status, error.message)
      console.log('📡 API | Dataset not found', 'Data Not Found')
      break

    case 422:
      console.error(error.response.status, error.message, error.response.data.detail)
      console.log('📡 API | Validation error', 'Unprocessable Content')
      break

    default:
      console.error(error.response.status, error.message)
  }
  return Promise.reject(error)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhillip BoatengView Question on Stackoverflow
Solution 1 - JavascriptSteveView Answer on Stackoverflow
Solution 2 - JavascriptJeroen WienkView Answer on Stackoverflow
Solution 3 - JavascriptSupervisionView Answer on Stackoverflow
Solution 4 - JavascriptAfdal MtkView Answer on Stackoverflow
Solution 5 - JavascriptRyan-Neal MesView Answer on Stackoverflow
Solution 6 - JavascriptAnthony ArtemievView Answer on Stackoverflow
Solution 7 - JavascriptchrislowView Answer on Stackoverflow
Solution 8 - JavascriptSimon KlimekView Answer on Stackoverflow