msw icon indicating copy to clipboard operation
msw copied to clipboard

TypeError: Network Request Failed

Open Smankusors opened this issue 3 years ago • 11 comments

Describe the bug

I received this error whenever there's code error on the handler code.

Environment

This unit testing running on Node environment

  • msw: 0.35.0
  • nodejs: 16.6.0
  • npm: 7.24.1

To Reproduce

Take a look at the example of the handler code below:

import { rest } from 'msw'

export const handlers = [
  rest.post('/login', (req, res, ctx) => {
    const { username } = req.body
    i = 1 / 0
    return res(
      ctx.json({
        id: 'f79e82e8-c34a-4dc7-a49e-9fadc0979fda',
        username,
        firstName: 'John',
        lastName: 'Maverick',
      })
    )
  }),
]

Expected behavior

The error should appear like this when testing

    ReferenceError: i is not defined
        at resolver ([project path]\src\mocks\handlers.js:6:6)
        at [rest of stack traces]

Current behavior

But instead, TypeError appears

    TypeError: Network request failed

      at node_modules/whatwg-fetch/dist/fetch.umd.js:535:18
      at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:516:19)

It seems like when the handler code failed, there's no response being sent back, resulting what it looks like timeout.

More info

I'm able to make the error shows up in the console by editing this line

https://github.com/mswjs/msw/blob/11bb2441e102666184188f9f576ac65e59b1be9d/src/handlers/RequestHandler.ts#L235

into this

      try {
        result = this.resolverGenerator || (await resolver(req, res, ctx))
      } catch (error) {
        console.error(error)
        return null
      }

but it's kinda ugly? What's best approach for this?

Smankusors avatar Nov 07 '21 15:11 Smankusors

Hey, @Smankusors.

The current behavior is correct. MSW stands for a mocked server-side code you're writing. If there'd be such a code as 1 / 0 on the server, you wouldn't get the direct exception for it (normally). Instead, your request would fail, receive a 500 response status code, with some additional information (if such was implemented by the server).

That's exactly how MSW behaves:

  1. Your request receives a 500 response (Network request failed). Note that this behavior is controlled by the request client and window.fetch may produce one exception while something like axios—another.
  2. The actual 500 response contains the original exception you're expecting in its body. Locate that failed request in the "Network" tab, click on it, choose to "Preview" its body. You will see a JSON body with the error and its location.

That being said, if this behavior is confusing to developers, I see little harm in duplicating the error message directly to the console for better visibility. But I'd still leave the behavior I described above intact.

kettanaito avatar Nov 08 '21 13:11 kettanaito

If I'm not mistaken, such exception will bubble to this catch block in createRequestListener function:

https://github.com/mswjs/msw/blob/f6fbd6c94d86d54ee13d20f0128589332cbddcbf/src/utils/worker/createRequestListener.ts#L69-L96

This is also how such exceptions are translated to 500 error responses (signaling NETWORK_ERROR or INTERNAL_ERROR events to the worker).

I believe if we add the suggested console.error(error) call at the beginning of this catch block we'll get the expected behavior.

@Smankusors, would you be interested in working on this? I will support you during the code review if you decide so.

kettanaito avatar Nov 08 '21 13:11 kettanaito

yeah it should return 500 response, but it doesn't. The timeout returned instead.

I have tried console.log everywhere in the createRequestListener.ts, but not a single log is even appear on the console

Take a look of my modified createRequestListener

https://github.com/Smankusors/msw/blob/52ffe4117d89820c7c29152e860c4fa8ff15e2ee/src/utils/worker/createRequestListener.ts

Smankusors avatar Nov 08 '21 17:11 Smankusors

My jest-tests exit the process because of this, instead of just failing the test. The fix doesn't have been merged / released yet, i think.

teamgroove avatar Apr 28 '22 10:04 teamgroove

In my case adding the full Url, it didn't show the error.

const login = rest.post('http://localhost:3001/api/auth/login', (req, res, ctx) => {

angeld287 avatar Jun 29 '22 00:06 angeld287

Hey. To add to this type of error, I got the network request failed issue because I didn't pass in a correct handler to server.use

server.use(
			`${process.env.REACT_APP_BASE_API_URL}/inmt-journal/api/v1/journals`, (req, res, ctx) => res(
				ctx.status(200),
				ctx.json({
					objects: [],
				}),
			),
		);

In the above example, there is no rest.get used. Seems similar to all issues pointed out in this thread.

tyricec avatar Aug 31 '22 20:08 tyricec

I've just spent one day of debugging trying to figure out what's causing mine 'TypeError: Network Request Failed'. I've turned debug mode one, got some more details: xhr:request GET http://localhost/api/feature-flags?_=1670508691045 middleware function threw an exception! TypeError: Missing parameter name at 23 at lexer (/node_modules/path-to-regexp/src/index.ts:72:24) at parse (/node_modules/path-to-regexp/src/index.ts:141:18) at stringToRegexp (/node_modules/path-to-regexp/src/index.ts:493:25) at pathToRegexp (/node_modules/path-to-regexp/src/index.ts:620:10) at match (/node_modules/path-to-regexp/src/index.ts:379:14)

I kept digging and then I noticed that one of the handlers has extra " inside... rest.get('"http://localhost/api/$metadata', (_, res, ctx) => res(ctx.status(200))) Error handling should be improved to avoid such situations

maaaaagda avatar Dec 08 '22 14:12 maaaaagda

@maaaaagda, thanks for reporting this. Have you tried running that problematic use case with the onUnhandledRequest option of MSW? It's designed precisely for that—to report typos in handlers and even suggest similar handlers you might have meant instead.

In fact, this option has been set to warn for quite some time now, so you should've seen a warning that includes info that the request didn't have a handler and a list of similar handlers (where it should've printed the problematic one).

kettanaito avatar Dec 08 '22 17:12 kettanaito

I also highly recommend updating to the latest version of msw to whoever still experiences this. Unhandled exceptions in request handlers are handled as 500 responses, this always was like this but there might've been a bug that disrupted this behavior. This is true for both Node and the browser, although the issue has been originally reported for Node.

Also, the original error message coming from whatwg-fetch, which implements how Fetch API reacts to unhandled exceptions, is completely correct:

TypeError: Network request failed

If there's any error in the request processing chain, you will get this TypeError. In that regard, I think MSW behaves correctly.

This needs to be put into an integration test, it looks fairly easy to do. The input for that test is a handler that references a non-existing variable (e.g. i), and the expected behavior it A) to return 500 response; B) to print TypeError: Network request failed from fetch (if fetch is used).

kettanaito avatar Dec 08 '22 17:12 kettanaito

@kettanaito I have onUnhandledRequest: 'error' always on. I also printed the handlers before as well. But there were no errors until request was intercepted and finished with Network request failed. I'm using "msw": "^0.48.0" but I'll update it. In my case something went wrong with parsing the url, as the match from path-to-regexp thrown, see https://github.com/mswjs/msw/blob/42cdbc79654d90b3edce747ea044513f2f964958/src/utils/matching/matchRequestUrl.ts#L66. cleanPath was not given and path-to-regexp expected it to be a non empty string

maaaaagda avatar Dec 09 '22 07:12 maaaaagda

Hi @kettanaito are you still accepting contributions to solve this issue?

EduardoSimon avatar Oct 04 '23 21:10 EduardoSimon