洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@[email protected]

I'm troubleshooting a mysterious TypeError: fetch failed exception when using .js's built-in fetch() function. When I make the same request in or , it responds fine. Anyone know why this only happens in Node.js?

Deno 2.1.4
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
> await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci");
Response {
  body: ReadableStream { locked: false },
  bodyUsed: false,
  headers: Headers {
    "alt-svc": 'h3=":443"; ma=2592000',
    "cache-control": "public, max-age=15",
    "content-length": "10828",
    "content-security-policy": "default-src 'self' 'unsafe-inline'; img-src *; media-src *; frame-ancestors *",
    "content-type": "text/html; charset=utf-8",
    date: "Mon, 30 Dec 2024 15:59:09 GMT",
    server: "Caddy",
    "strict-transport-security": "max-age=15552000; preload",
    vary: "Origin, Accept",
    "x-frame-options": "DENY"
  },
  ok: true,
  redirected: false,
  status: 200,
  statusText: "OK",
  url: "https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci"
}
>
Deno 2.1.4 exit using ctrl+d, ctrl+c, or close() REPL is running with all permissions allowed. To specify permissions, run `deno repl` with allow flags. > await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci"); Response { body: ReadableStream { locked: false }, bodyUsed: false, headers: Headers { "alt-svc": 'h3=":443"; ma=2592000', "cache-control": "public, max-age=15", "content-length": "10828", "content-security-policy": "default-src 'self' 'unsafe-inline'; img-src *; media-src *; frame-ancestors *", "content-type": "text/html; charset=utf-8", date: "Mon, 30 Dec 2024 15:59:09 GMT", server: "Caddy", "strict-transport-security": "max-age=15552000; preload", vary: "Origin, Accept", "x-frame-options": "DENY" }, ok: true, redirected: false, status: 200, statusText: "OK", url: "https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci" } >
Welcome to Bun v1.1.42
Type ".help" for more information.
[!] Please note that the REPL implementation is still experimental!
    Don't consider it to be representative of the stability or behavior of Bun overall.
> await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci");
Response {}
>
Welcome to Bun v1.1.42 Type ".help" for more information. [!] Please note that the REPL implementation is still experimental! Don't consider it to be representative of the stability or behavior of Bun overall. > await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci"); Response {} >
Welcome to Node.js v23.5.0.
Type ".help" for more information.
> await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci");
Uncaught TypeError: fetch failed
    at node:internal/deps/undici/undici:13484:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async REPL1:1:33 {
  [cause]: AggregateError [ETIMEDOUT]:
      at internalConnectMultiple (node:net:1139:18)
      at internalConnectMultiple (node:net:1215:5)
      at Timeout.internalConnectMultipleTimeout (node:net:1739:5)
      at listOnTimeout (node:internal/timers:616:11)
      at process.processTimers (node:internal/timers:549:7) {
    code: 'ETIMEDOUT',
    [errors]: [ [Error], [Error] ]
  }
}
>
Welcome to Node.js v23.5.0. Type ".help" for more information. > await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci"); Uncaught TypeError: fetch failed at node:internal/deps/undici/undici:13484:13 at process.processTicksAndRejections (node:internal/process/task_queues:105:5) at async REPL1:1:33 { [cause]: AggregateError [ETIMEDOUT]: at internalConnectMultiple (node:net:1139:18) at internalConnectMultiple (node:net:1215:5) at Timeout.internalConnectMultipleTimeout (node:net:1739:5) at listOnTimeout (node:internal/timers:616:11) at process.processTimers (node:internal/timers:549:7) { code: 'ETIMEDOUT', [errors]: [ [Error], [Error] ] } } >
Chris​‌​‬ Hayes‌​​​'s avatar
Chris​‌​‬ Hayes‌​​​

@[email protected] · Reply to 洪 民憙 (Hong Minhee)'s post

@hongminhee Testing node fetch on my side works fine.

I'd be curious what happens if you copy the user-agent sent with your deno request, and used that in your node.js request. May be firewall related.

A terminal displaying a successful HTTP fetch request to a URL, returning a status code 200 with detailed HTTP headers and body information.
A terminal displaying a successful HTTP fetch request to a URL, returning a status code 200 with detailed HTTP headers and body information.
洪 民憙 (Hong Minhee)'s avatar
洪 民憙 (Hong Minhee)

@[email protected] · Reply to 洪 民憙 (Hong Minhee)'s post

Okay, it seems to work when I configured Node.js's default DNS resolution order to "ipv6first"… 🤔

Welcome to Node.js v23.5.0.
Type ".help" for more information.
> const dns = await import("node:dns");
undefined
> dns.setDefaultResultOrder("ipv6first");
undefined
> await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci");
Response {
  status: 200,
  statusText: 'OK',
  headers: Headers {
    'alt-svc': 'h3=":443"; ma=2592000',
    'cache-control': 'public, max-age=15',
    'content-length': '10828',
    'content-security-policy': "default-src 'self' 'unsafe-inline'; img-src *; media-src *; frame-ancestors *",
    'content-type': 'text/html; charset=utf-8',
    date: 'Mon, 30 Dec 2024 16:32:22 GMT',
    server: 'Caddy',
    'strict-transport-security': 'max-age=15552000; preload',
    vary: 'Origin, Accept',
    'x-frame-options': 'DENY'
  },
  body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },
  bodyUsed: false,
  ok: true,
  redirected: false,
  type: 'basic',
  url: 'https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci'
}
>
Welcome to Node.js v23.5.0. Type ".help" for more information. > const dns = await import("node:dns"); undefined > dns.setDefaultResultOrder("ipv6first"); undefined > await fetch("https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci"); Response { status: 200, statusText: 'OK', headers: Headers { 'alt-svc': 'h3=":443"; ma=2592000', 'cache-control': 'public, max-age=15', 'content-length': '10828', 'content-security-policy': "default-src 'self' 'unsafe-inline'; img-src *; media-src *; frame-ancestors *", 'content-type': 'text/html; charset=utf-8', date: 'Mon, 30 Dec 2024 16:32:22 GMT', server: 'Caddy', 'strict-transport-security': 'max-age=15552000; preload', vary: 'Origin, Accept', 'x-frame-options': 'DENY' }, body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true }, bodyUsed: false, ok: true, redirected: false, type: 'basic', url: 'https://social.zarchbox.fr/notes/a2dn3k8kt5hm3gci' } >