window.fetch() requests that return 401 code do not get their data returned

Not reproducible Issue #14320968


Wojciech K.
Oct 20, 2017
This issue is public.
Found in
  • Microsoft Edge
Found in build #
Reported by 5 people

Sign in to watch or report this issue.

Steps to reproduce

When trying to implement authentication in an application, I’ve come across the following - when using window.fetch to make an API call that results in 401 error, the response is not returned and an empty string is returned instead. For example:

window.fetch('/api/method', {
  method: 'POST', body: '{"data":"data"}'
}).then(function(r) {return r.json();})
.then(function(ok) {console.log('OK', ok);},
  function(e) {console.log('ERROR',err);});

If /api/method returns any other HTTP code (i.e. 200, 201, 404), then the result is returned and OK logs the json data. However, if the returned code is 401, .json() throws an error that it can’t parse the body.

All other browsers I’ve tested (Chrome 61, Firefox 56) do return the response properly and the issue only happens with Edge.

Ideally the authentication model for the application I am working on will depend on HTTP code being 401 and the response providing enough information to authenticate the user by the frontend and perform auth again.

This does not seem to be possible with Edge.

As 403 code is already used for other things, it can’t be switched to that code. Also 401, not 403 should be used to indicate the application has to provide Authorization HTTP header.


0 attachments

    Comments and activity

    • Microsoft Edge Team

      Changed Assigned To to “Steven K.”

    • Do you have a working repro for this?  Client and server side?  A simplified repro would help get this sorted out as fast as possible.  Perhaps you are aware of a w3c test case for this scenario?  I took a quick look and did not find anything yet.  I will keep looking.

      Appreciate the help,


    • Sure,

      Below is a sample code in Go that serves sample JSON data as /test/(code) and a sample HTML+JS page that demonstrates the issue.

      I can provide a compiled binary if this helps in any way, but this just uses vanilla Go packages so all you should need to build is to get the Go installer/zip file and run go build inside the directory where you put the code below as main.go. The example is also relatively trivial and is just about a server that returns all the codes.

      It logs results to console.

      On Chrome/Firefox, the output is more or less:

      Parsed JSON for 200 : {"sample":"data"}
      Parsed JSON for 201 : {"sample":"data"}
      GET 500 (Internal Server Error)
      Parsed JSON for 500 : {"sample":"data"}
      GET 404 (Not Found)
      Parsed JSON for 404 : {"sample":"data"}
      GET 403 (Forbidden)
      Parsed JSON for 403 : {"sample":"data"}
      GET 401 (Unauthorized)
      Parsed JSON for 401 : {"sample":"data"}
      All tests have finished

      For Edge it is:

       Parsed JSON for 200 : {"sample":"data"}
       Parsed JSON for 201 : {"sample":"data"}
       Parsed JSON for 500 : {"sample":"data"}
       HTTP500: SERVER ERROR - The server encountered an unexpected condition that prevented it from fulfilling the request.
      (Fetch)GET -
       Parsed JSON for 404 : {"sample":"data"}
       HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
       Parsed JSON for 403 : {"sample":"data"}
       HTTP403: FORBIDDEN - The server understood the request, but is refusing to fulfill it.
      (Fetch)GET -
      Error for 401 : SyntaxError: Failed to read.
       All tests have finished (33,25)
       HTTP401: DENIED - The requested resource requires user authentication.
      (Fetch)GET -

      The error SyntaxError: Failed to read. is because the response is not fetched and so parsing fails.

      If you replace return r.json() with return r.text() and replace JSON.stringify(r)) with r) (so change it to fetch and log the actual text returned), it will log empty response for 401 and proper JSON returned by the server for any other code.

      package main
      import (
      var (
          json = `{"sample": "data"}`
      // return a JSON data (see above) along with proper exit code
      // this is set up to serve as  /test/(code)
      // i.e. /test/401, /test/200 and return requested code
      func returnJSON(w http.ResponseWriter, r *http.Request) {
          splitURL := strings.Split(r.RequestURI, "/")
          code, err := strconv.Atoi(splitURL[len(splitURL)-1])
          // if parsing the code from
          if err != nil {
              http.Error(w, fmt.Sprintf("%q", err), 500)
          w.Header().Set("Content-Type", "application/json")
          fmt.Fprintf(w, "%s", json)
      // return HTML with the script that demonstrates the issue
      func returnPage(w http.ResponseWriter, r *http.Request) {
          fmt.Fprintln(w, `
                      Please open console window
      func main() {
          http.HandleFunc("/", returnPage)
          http.HandleFunc("/test/", returnJSON)
          http.ListenAndServe(":8081", nil)
    • Hello, is there any update on this?

      I would want to understand if this is something where Edge will be consistent with other browsers (even if this will take time to be delivered to all users of the browser) or not.

      The site I’m working on is affected and knowing if fixing it would be temporary solution or if we need to look for a permanent one would help us in deciding.

    • I found this this when working with fetch and WebAPI 2. It is easy to reproduce:
      Server code snippet:

      [HttpGet, Route("~/api/Throw401ErrorTest")]
      public IHttpActionResult Throw401ErrorTest() {
        return Content(HttpStatusCode.Unauthorized, "SPECIFIC_REASON");

      Client code snippet:

        .then(function (response) {
          return response.text();
        .then(function (data) {

      All other modern browsers will show “SPECIFIC_REASON” in the console - Edge does not. Even more frustrating is that the fetch polyfill ( also works as expected.

    • Hello, is there any update on this ? We’ve got the same problem on our webapp (windows.fetch() does not return payload for 401 answers where other browsers work perfectly).

    • (build 42.17134.1.0)

    • I am also experiencing this issue with build 41.16299.726.0

    • Microsoft Edge Team

      Changed Assigned To from “Steven K.” to “Zachariah L.”

    • Hi Wojciech!

      Thank you for contacting us about this issue! To help with my investigation could you provide me with a zip containing both client and server code which reproduces this problem?


    • Hi Wojciech!

      For now, I will resolve this issue as "Not Reproducible". If you are still experiencing this problem then please feel free to reopen this issue with the information I requested and I will resume my investigation.



    • Microsoft Edge Team

      Changed Status to “Not reproducible”

    • Please parse credentials: ‘include’ as an option with fetch, this will fix it. It’s usually happening when your location is .htaccess password protected. Looks like only Edge got this problem so far.

      fetch(url, {
      credentials: ‘include’

    • Please parse credentials: ‘include’ as an option with fetch, this will fix it. It’s usually happening when your location is .htaccess password protected. Looks like only Edge got this problem so far.

      fetch(url, {
      credentials: ‘include’

    You need to sign in to your Microsoft account to add a comment.

    Sign in