msw
msw copied to clipboard
Error: Premature close
Prerequisites
- [X] I confirm my issue is not in the opened issues
- [X] I confirm the Frequently Asked Questions didn't contain the answer to my issue
Environment check
- [X] I'm using the latest
msw
version - [X] I'm using Node.js version 14 or higher
Node.js version
v16.14.1
Reproduction repository
https://github.com/molvqingtai/resreq/blob/35d7e2e19d3bbbca6d4c55f5fd6119db7afdc30d/tests/main.spec.ts
Reproduction steps
I use Vitest test and use some Polyfill:
- node-fetch v3.2.3
- abort-controller v3.0.0
- formdata-node v4.3.2
Current behavior
When I run the test, there is a high probability that this error will occur:
❯ __tests__/main.spec.ts (2)
❯ Test methods (2)
√ GET request
× POST request
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
FAIL __tests__/main.spec.ts > Test methods > POST request
Error: Premature close
❯ NodeClientRequest.emit node:events:402:35
❯ NodeClientRequest.emit node_modules/.pnpm/@[email protected]/node_modules/@mswjs/interceptors/lib/interceptors/ClientRequest/NodeClientRequest.js:309:38
❯ Socket.socketCloseListener node:_http_client:423:9
❯ Socket.emit node:events:402:35
❯ TCP.<anonymous> node:net:687:12
Expected behavior
No errors
Hey, @molvqingtai. Thanks for reporting this!
I confirm I can reproduce the issue, although only at times. This seems to be the Node.js error thrown when the socket is closed by the readable stream has not ended:
Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close
at new NodeError (node:internal/errors:371:5)
at NodeClientRequest.onclose (node:internal/streams/end-of-stream:140:30)
at NodeClientRequest.emit (node:events:532:35)
at NodeClientRequest.emit (/Users/kettanaito/Projects/contrib/msw-1169-premature-close/node_modules/@mswjs/interceptors/lib/interceptors/ClientRequest/NodeClientRequest.js:309:38)
at Socket.socketCloseListener (node:_http_client:418:9)
at Socket.emit (node:events:532:35)
at TCP.<anonymous> (node:net:687:12) {
code: 'ERR_STREAM_PREMATURE_CLOSE'
}
https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/internal/streams/end-of-stream.js#L140
And this is how it checks if the stream is finished:
https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/internal/streams/end-of-stream.js#L46-L51
We may need to look into the state of the stream in the interceptors and make sure it's properly marked as finished. But I suspect that the issue is in socket closing the connection before the mocked response is written (I think it will close it immediately once connecting to 127.0.0.1 rejects).
I'm getting the same error with jest when upgrading from v0.36.3
.
In my case:
-
v0.36.3
didn't trigger the issue (my initial version) -
v0.36.8
didn't trigger the issue -
v0.38.0
trigger the issue -
v0.38.1
trigger the issue -
v0.38.2
trigger the issue -
v0.39.2
trigger the issue
By looking into the changelog of the v0.38.0, it could linked to the interceptor upgrade.
Thanks for checking the version compatibility, @armandabric!
I'd expect the issue to originate from @mswjs/[email protected] as it's related to the request interceptor algorithm changes we've introduced in that version. I wrote about this change here.
The root cause here is the socket terminates the connection when it cannot make one, terminating the request while its readable stream is still handling data, resulting in premature close. I think it's okay that me make the connection (see my reasoning in the article above) but we need to make sure that socket errors do not propagate to the ClientRequest
internals before we're sure that those errors are relevant and not just happen because we're mocking endpoints.
I do welcome anybody with the will and time to look into Node.js internals I've posted above and figure out the correct way for us to prevent socket errors from bubbling to the ClientRequest
unless we have to replay them. I wanted to focus on other things at the moment so I can't put this at the top of my priorities list.
I wonder if this is caused by node-fetch
listening to the Socket errors instead of ClientRequest errors. While we're silencing the latter, Socket errors still occur and may halt the request client if it reacts to them.
We should look into this in the interceptors library.
I wonder if this is caused by
node-fetch
listening to the Socket errors instead of ClientRequest errors. While we're silencing the latter, Socket errors still occur and may halt the request client if it reacts to them.We should look into this in the interceptors library.
I am using cross-fetch for mocking fetch api.
"cross-fetch": "^3.1.5",
I'm seeing a weird error that seems unrelated: when doing an axios.put
, the request hangs forever unless I set a timeout. msw doesn't properly track this request: it neither responds to it nor does it trigger the onUnhandledRequest
.
Other http verbs seem to work fine.
I'm mentioning it here though because of @armandabric's comment regarding versions: the issue I'm facing doesn't happen in v0.36.8
but it happens consistently in 0.38.0
and newer versions.
This should be fixed in msw@latest
. Please upgrade and let me know if you still experience this. There's been a lot of work done on the Node.js interception over the past year.