undici
undici copied to clipboard
`UND_ERR_SOCKET` in fetch
Sometimes fetch
ends up with exception:
{
cause: {
name: "SocketError",
code: "UND_ERR_SOCKET",
socket: {
localAddress: "192.168.1.33",
localPort: 12345,
remoteAddress: "X.Y.Z.W",
remotePort: 443,
remoteFamily: "IPv4",
timeout: undefined,
bytesWritten: 651,
bytesRead: 441,
},
message: "other side closed",
stack: "SocketError: other side closed\n at TLSSocket.onSocketEnd (node:internal/deps/undici/undici:9499:26)\n at TLSSocket.emit (node:events:524:35)\n at endReadableNT (node:internal/streams/readable:1359:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:82:21)"
},
message: "fetch failed",
stack: "TypeError: fetch failed\n at Object.fetch (node:internal/deps/undici/undici:12789:11)\n at async Object.xyzFunc..."
}
Unfortunately, we don't have a reproducible code, because of complexity of application, the initial fetch
requests work, but after making some further fetch
we sporadically get the error. Do you have any suggestions? Have tried all workaround found in internet, but nothing worked. The exact request which fails with node fetch
, works from postman
.
( Windows 11, tested results below with v19.6, however same issue happens in 18.14)
That error should also have a message...?
That error should also have a message...?
sorry, I didnt notice I hadnt copied full object. I've updated the message, please refresh page to see it.
So that looks like the server has just forcefully killed the connection... doesn't seem client related
can you give me hints what I should refer to? I havent faced any issue across numerous different libs, and havent faced http/s request which ends up without returning response. Server returns some response and headers, and our app works with node-fetch
(re-tested at this moment exacty, and I can confirm), but not with builtin fetch.
hard to understand the criteria when it happens, almost impossible to find out, spent several hours already. What I spotted, this might theoretically be (?) related to VSCODE debugger, as when i run the code through debugger (but even sometimes works if I quickly step over the method, but sometimes not when I run step by step). well, what I can say is that it perfectly works through node-fetch
. unfortunately, I cant share the app and can only send a screenrecord (or possible remote session too) if there will be interest from your side.
This happens when the socket is closed before receiving a status code (more or less). I believe it's been a known 'issue' for a while now.
repro
import { fetch } from 'undici'
import { createServer } from 'http'
import { once } from 'events'
const server = createServer((req, res) => {
res.socket.end()
}).listen(0)
await once(server, 'listening')
await fetch(`http://localhost:${server.address().port}`)
if it works with other libs (i.e. node-fetch
) is not there any thoughts whether which this bug concerns to? undici or node itself?
In the case above, it will also fail with node-fetch (which uses node's http and https modules). If it works with node-fetch, then I'd consider it a bug in undici. However we'd need a small repro to work with.
This is a working repro anyone can test (I will try to maintain server
for as long as possible):
import got from "got";
const testSocketError = async () => {
const server = "http://pickering.entrydns.org:8085";
console.log("******Using fetch:")
await fetch(server)
.then(async resp => {
await resp.text()
.then(t => {
console.log(t);
})
.catch(err => {
console.error("***Error in text():")
console.error(err.message);
console.error(err.cause?.code);
console.error(err.cause?.message);
});
})
.catch(err => {
console.error("***Error in fetch():")
});
console.log("\n*****Using the got package:");
await got.get(server)
.then(
response => {
console.log("Result from `got`:", response.body?.substring(0,50), "...");
}
).catch(err => {
console.error(err.message);
});
};
testSocketError();
Output from above is:
***Error in text():
terminated
UND_ERR_SOCKET
closed
*****Using the got package:
Result from `got`: <HTML><HEAD><script>top.location.href='/Main_Login ...
PS: I am running fetch
from inside Node v18.1.0.
The fetch implementation in Node v18.1.0 is quite buggy. Could you update to the latest Node.js v18 line and check if the problem still holds?
Yes, .text()
works with v18.15.0. However, the output is more than just the body of the response. It looks like body + headers + blank line + body.
Is it possible to catch this acception? I am reading a stream from remote api and this error occurs, but cannot be caught in try/catch.
[1] node:internal/deps/undici/undici:13946 [1] fetchParams.controller.controller.error(new TypeError("terminated", { [1] ^ [1] [1] TypeError: terminated [1] at Fetch.onAborted (node:internal/deps/undici/undici:13946:53) [1] at Fetch.emit (node:events:513:28) [1] at Fetch.terminate (node:internal/deps/undici/undici:13208:14) [1] at Object.onError (node:internal/deps/undici/undici:14041:36) [1] at Request.onError (node:internal/deps/undici/undici:7568:31) [1] at errorRequest (node:internal/deps/undici/undici:9727:17) [1] at TLSSocket.onSocketClose (node:internal/deps/undici/undici:9178:9) [1] at TLSSocket.emit (node:events:525:35) [1] at node:net:320:12 [1] at TCP.done (node:_tls_wrap:588:7) { [1] [cause]: SocketError: other side closed [1] at TLSSocket.onSocketEnd (node:internal/deps/undici/undici:9157:26) [1] at TLSSocket.emit (node:events:525:35) [1] at endReadableNT (node:internal/streams/readable:1359:12) [1] at process.processTicksAndRejections (node:internal/process/task_queues:82:21) { [1] code: 'UND_ERR_SOCKET', [1] socket: { [1] localAddress: '192.168.1.76', [1] localPort: 56198, [1] remoteAddress: '104.18.35.163', [1] remotePort: 443, [1] remoteFamily: 'IPv4', [1] timeout: undefined, [1] bytesWritten: 530, [1] bytesRead: 5811803 [1] } [1] } [1] }
Hey fellow undici users !
-
In September we removed node-fetch from an app to use internal node fetch.
- We detected some UND_ERR_SOCKET errors related to API calls using fetch that we didn't have before.
- Back then, I found this issue and, as the app was running on Node v18.6.0, I didn't add a comment because @mcollina pointed out that the fetch implementation might be buggy in v18.
-
In October, we migrated Node to the latest LTS and are now using Node v20.10.0.
- We were hopeful, but the problem persists
- To assert that the problem was on the client-side of the call, I polyfilled fetch globally with node-fetch v3
- no more errors
Do you have any ideas ?
Sorry, but you have not really provided us with any information we use to help you... other than that "We detected some UND_ERR_SOCKET errors".
Hey fellow undici users !
In September we removed node-fetch from an app to use internal node fetch.
- We detected some UND_ERR_SOCKET errors related to API calls using fetch that we didn't have before.
- Back then, I found this issue and, as the app was running on Node v18.6.0, I didn't add a comment because @mcollina pointed out that the fetch implementation might be buggy in v18.
In October, we migrated Node to the latest LTS and are now using Node v20.10.0.
We were hopeful, but the problem persists
To assert that the problem was on the client-side of the call, I polyfilled fetch globally with node-fetch v3
- no more errors
Do you have any ideas ?
I have this exact same problem in node 20.
Sorry, but you have not really provided us with any information we use to help you... other than that "We detected some UND_ERR_SOCKET errors".
Not sure how to produce an example when it's sporadic. Looks like it is when there is quite a lot of concurrent requests.
A few things:
- The error listed at the top literally is saying that the connection was cut. It's TCP, and a connection can be broken for any reason, even ones unrelated to fetch().
- usually it's due to configuring the various timeouts we have by default. Change the settings and experiment in your system.
- HTTP at scale it's hard.
If we have a reproduction, we can fix it. Please give us:
- a server
- a client program that passes with got/node-fetch/http.request
- a client program that errors with undici fetch()
We will investigate this.
Alternatively, somebody would have to contract one of us to dig into their private codebase and identify the problem. Note that it is extremely likely it is related to some other piece of your infrastructure cutting the connection for whatever reason.