msw
msw copied to clipboard
TypeError: Network Request Failed
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?
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:
- Your request receives a 500 response (
Network request failed
). Note that this behavior is controlled by the request client andwindow.fetch
may produce one exception while something likeaxios
—another. - 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.
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.
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
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.
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) => {
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.
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, 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).
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 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
Hi @kettanaito are you still accepting contributions to solve this issue?