undici
undici copied to clipboard
Uncaught TypeError: terminated
Bug Description
Uncaught TypeError: terminated
Reproducible By
TEST_URL
- may be status 401, other status is not tested.
- MUST have not-empty-body, so things like
https://httpbin.org/status/401will not work - In this reproduce case, total body only have one chunk.
> var{fetch}=await import('undici');
> r=await fetch(TEST_URL);
Response
> rd=r.body.getReader();
ReadableStreamDefaultReader
> c0=await rd.read();
{ done: false, value: Uint8Array(141) }
Expected Behavior
Firefox
> c1=await rd.read();
{ done: true, value: undefined }
Logs & Screenshots
Node v18.10.0
> c1=await rd.read();
Uncaught TypeError: terminated
at Fetch.onAborted (undici/lib/fetch/index.js:1874:49)
at Fetch.emit (node:events:513:28)
at Fetch.emit (node:domain:552:15)
at Fetch.terminate (undici/lib/fetch/index.js:83:10)
at Object.onError (undici/lib/fetch/index.js:2015:34)
at Request.onError (undici/lib/core/request.js:265:27)
at errorRequest (undici/lib/client.js:1722:13)
at Socket.onSocketClose (undici/lib/client.js:985:5)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:552:15) {
[cause]: SocketError: closed
at Socket.onSocketClose (undici/lib/client.js:967:31)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:552:15)
at TCP.<anonymous> (node:net:313:12)
at TCP.callbackTrampoline (node:internal/async_hooks:130:17) {
code: 'UND_ERR_SOCKET',
socket: {
localAddress: undefined,
localPort: undefined,
remoteAddress: undefined,
remotePort: undefined,
remoteFamily: undefined,
timeout: undefined,
bytesWritten: 168,
bytesRead: 334
}
}
}
Environment
- Firefox
- Node v18.10.0
- undici 5.11.0
Additional context
Related https://github.com/nodejs/undici/issues/1490
Can you also include a small server?
undici Error
An real world example, I put undici in unit test, and it failed. Below is a curl log.
no Content-Length
< HTTP/1.0 401 Unauthorized
< Foo: foo
< Connection: close
< Bar: bar
<
{{body}}
* Closing connection 0
undici OK
The response I can reproduce in nodejs.
no Content-Length
< HTTP/1.1 401 Unauthorized
< Foo: foo
< Connection: close
< Bar: bar
< Transfer-Encoding: chunked
<
* Closing connection 0
{{body}}
Conclusion
Seems like root cause is one of below
- HTTP/1.0. No idea how to reproduce that in node
- Lack of
Transfer-EncodingandContent-Lengthat the same time - Not sure why below curl log is different, maybe
Transfer-Encoding?
{{body}}
* Closing connection 0
Thanks for reporting. Undici is an HTTP/1.1 client and this issue is about HTTP/1.0 support. I do not think we have the bandwidth to work on this issue right now, but we'll be very happy if somebody would like to work on this.
https://github.com/loynoir/reproduce-undici-1688
node.js
✔ fetch test: cgi with-content-length
1) fetch test: cgi without-content-length
1 passing (60ms)
1 failing
1) fetch test: cgi without-content-length:
TypeError: terminated
at Fetch.onAborted (node_modules/undici/lib/fetch/index.js:1874:49)
at Fetch.emit (node:events:513:28)
at Fetch.terminate (node_modules/undici/lib/fetch/index.js:83:10)
at Object.onError (node_modules/undici/lib/fetch/index.js:2015:34)
at Request.onError (node_modules/undici/lib/core/request.js:265:27)
at errorRequest (node_modules/undici/lib/client.js:1722:13)
at Socket.onSocketClose (node_modules/undici/lib/client.js:985:5)
at Socket.emit (node:events:513:28)
at TCP.<anonymous> (node:net:313:12)
browser
✔ fetch test: cgi with-content-length
✔ fetch test: cgi without-content-length
First time experiencing this one as well, just today.
From my experience this happens when fetch response status code is different other than 200. It seems some status code like 302 and 307 does not like having response body so doing await response.json() results into TypeError: terminated. Status code 401 is fine to receive a body so it works. I would like to mention #426 to be a more reliable solution going forward so people could stop shooting themselves in the foot.