How to get Readable error response from javascript Fetch api? How to get Readable error response from javascript Fetch api? reactjs reactjs

How to get Readable error response from javascript Fetch api?


Since the text is hidden inside promise within response object, it needs to be handled like a promise to see it.

fetch(bla)    .then(res => {      if(!res.ok) {        res.text().then(text => throw Error(text))       }      else {       return res.json();     }        })    .catch(err => {       console.log('caught it!',err);    });    


Similar to your answer, but with a bit more explanation... I first check if the response is ok, and then generate the error from the response.text() only for the cases that we have a successful response. Thus, network errors (which are not ok) would still generate their own error without being converted to text. Then those errors are caught in the downstream catch.

Here is my solution - I pulled the core fetch function into a wrapper function:

const fetchJSON = (...args) => {  return fetch(...args)    .then(res => {      if(res.ok) {        return res.json()      }      return res.text().then(text => {throw new Error(text)})    })}

Then when I use it, I define how to handle my response and errors as needed at that time:

fetchJSON(url, options)  .then((json) => {    // do things with the response, like setting state:    this.setState({ something: json })  })  .catch(error => {    // do things with the error, like logging them:    console.error(error)  })


even though this is a bit old question I'm going to chime in.

In the comments above there was this answer:

const fetchJSON = (...args) => {  return fetch(...args)    .then(res => {      if(res.ok) {        return res.json()      }      return res.text().then(text => {throw new Error(text)})    })}

Sure, you can use it, but there is one important thing to bare in mind. If you return json from the rest api looking as {error: 'Something went wrong'}, the code return res.text().then(text => {throw new Error(text)}) displayed above will certainly work, but the res.text() actually returns the string. Yeah, you guessed it! Not only will the string contain the value but also the key merged together! This leaves you with nothing but to separate it somehow. Yuck!

Therefore, I propose a different solution.

fetch(`backend.com/login`, {   method: 'POST',   body: JSON.stringify({ email, password }) }) .then(response => {   if (response.ok) return response.json();   return response.json().then(response => {throw new Error(response.error)}) }) .then(response => { ...someAdditional code }) .catch(error => reject(error.message))

So let's break the code, the first then in particular.

.then(response => {       if (response.ok) return response.json();       return response.json().then(response => {throw new Error(response.error)})})

If the response is okay (i.e. the server returns 2xx response), it returns another promise response.json() which is processed subsequently in the next then block.

Otherwise, I will AGAIN invoke response.json() method, but will also provide it with its own then block of code. There I will throw a new error. In this case, the response in the brackets throw new Error(response.error) is a standard javascript object and therefore I'll take the error from it.

As you can see, there is also the catch block of code at the very end, where you process the newly thrown error. (error.message <-- the error is an object consisting of many fields such as name or message. I am not using name in this particular instance. You are bound to have this knowledge anyway)

Tadaaa! Hope it helps!

I've been looking around this problem and has come across this post so thought that my answer would benefit someone in the future.

Have a lovely day!

Marek