fetch: Catch a 401

Is there a way to catch a 401 error code? I first thought I could add it to the checkStatus function but it seems that a 401 does reject the promise.

But there is little to no information in the error object. https://cldup.com/R8VE0alk2z.png

Am I missing something?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 2
  • Comments: 24 (6 by maintainers)

Commits related to this issue

Most upvoted comments

For anyone who will have this issue in the future

Fetch API fails only if it can’t make a request. And if it can, fetch will be executed successfully even if it has a bad status. For example:

fetch('http://google.com')
  .then(response => {
    // response from server
    // here you can check status of response and handle it manually
    switch (response.status) {
      case 500: console.error('Some server error'); break;
      case 401: console.error('Unauthorized'); break;
      // ...
    }
    // or you can check if status in the range 200 to 299
    if (response.ok) {
      return response;
    } else {
      // push error further for the next `catch`, like
      return Promise.reject(response);
      // or another way
      throw Error(response.statusText);
    }
  })
  .catch(error => {
    // here you will get only Fetch API errors and those you threw or rejected above
    // in most cases Fetch API error will look like common Error object
    // {
    //   name: "TypeError",
    //   message: "Failed to fetch",
    //   stack: ...
    // }
  });

And here are some (not all) of the errors from Fetch API:

  • misspelled url like fetch('https::://hey.com')TypeError Failed to execute 'fetch' on 'Window': Failed to parse URL from https::://hey.com;
  • nonexistent url like fetch('http://hey')TypeError: Failed to fetch (GET http://hey/ net::ERR_NAME_NOT_RESOLVED);
  • you don’t have an internet connection fetch('https://google.com')TypeError: Failed to fetch (GET https://google.com/ net::ERR_NAME_RESOLUTION_FAILED)
  • because of the Content Security Policy fetch('https://google.com')TypeError: Failed to fetch (Refused to connect to 'https://google.com/' because it violates the following Content Security Policy directive: "connect-src 'self'...)
  • because of the CORS fetch('https://google.com')TypeError: Failed to fetch (Fetch API cannot load https://google.com/ has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource....)

The last two cases you can fix by adding (or editing) the appropriate headers on the server, if you have an access.

@dgraham that’s not correct. Fetch seems to reject the promise on a 401. So you don’t have access to the response object

I am seeing the same.

The polyfill is not active in browsers that include a native implementation of window.fetch, including Chrome and Firefox.

Here’s how you can detect and handle a 401 status code in the response from the server.

fetch('/').then(function(response) {
  if (response.status === 401) {
   // 401 returned from server
  } else {
    // another status code
  }
})

The promise is supposed to be rejected if CORS doesn’t allow it. I just tested with Chrome 45 and Chrome 47 and the promise is rejected by default when “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”

However if I add the Access-Control-Allow-Origin: * header to the 401 response from the other server, the 401 response is received just fine (promise is resolved) and its HTTP status is readable and correct.

@vdclouis Hey Louis, was you able to find a way to detect 401 code for rejected by CORS request? I’m stuck with same problem, I need to catch 503 status code

Is there a way to get those additional error messages to determine which error is occurring? For example (in Chrome 67), I’m running the following code:

fetch('https://fail').then(function(response){
	console.log('Fetch was successful', response);
}).catch(function(event){
	console.log('Fetch failed', event);
});

Which fails, but the only message in the console is TypeError: Failed to fetch. This example is obvious what the problem is, but when I have an actual URL in the fetch that resolves via a standard request, but fails using fetch() I cannot figure out what the specific problem is.

Edit: Thanks for the info below- in my situation error.response is undefined so it must be a network error like you described.

either way, this spec desperately needs to be fixed

@chrisblakley You can inspect event.response (your event argument is actually an Error instance) in the catch handler to access response.statusText and other information about a failed HTTP response.

If there is no error.response, then the fetch failed with what is usually a network error, and browsers don’t typically give us much information about those. See https://github.com/github/fetch/pull/562#issuecomment-330594122 for more context

Yes, yes it is.