Skip to content

fetch() in Node.js ignores connection timeout; no way to override 10s default #4215

@joe-oli

Description

@joe-oli

Bug Description

The global fetch() implementation in Node.js (since v18) uses Undici under the hood. However, there’s no way to configure connection-level timeouts, specifically the connectTimeout, which defaults to 10 seconds.

Even when using AbortSignal.timeout(ms) to a higher value, say 20000, it does not affect Undici's internal socket connection timeout.

Login error: TypeError: fetch failed at node:internal/deps/undici/undici:13502:13 at processTicksAndRejections (node:internal/process/task_queues:105:5) at async authenticateUser (C:\path\to\myApp\api-app\src\services\keycloak.ts:42:22) at async C:\path\to\myApp\api-app\src\routes\auth.ts:10:23 { [cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 10000ms) at onConnectTimeout (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:912:19) at Immediate._onImmediate (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:863:35) at processImmediate (node:internal/timers:491:21) { code: 'UND_ERR_CONNECT_TIMEOUT' } }

Reproducible By

The following fetch-based call always fails at 10 seconds, even though both AbortSignal.timeout() and agent were tried.

// Broken: fetch() fails after 10s regardless of signal
const undiciAgent = new Undici.Agent({
  connectTimeout: 20000,
  keepAliveTimeout: 1
});

const response = await fetch('http://10.2.2.164:80/realms/dev/protocol/openid-connect/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({ /* ... */ }),
  signal: AbortSignal.timeout(20000), // Makes no difference
  dispatcher: undiciAgent, // Makes no difference
});

Fails with:

ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 10000ms)

Error in console; NOTE THE PART timeout: 10000ms)
Login error: TypeError: fetch failed at node:internal/deps/undici/undici:13502:13 at processTicksAndRejections (node:internal/process/task_queues:105:5) at async authenticateUser (C:\path\to\myApp\api-app\src\services\keycloak.ts:42:22) at async C:\path\to\myApp\api-app\src\routes\auth.ts:10:23 { [cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 10000ms) at onConnectTimeout (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:912:19) at Immediate._onImmediate (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:863:35) at processImmediate (node:internal/timers:491:21) { code: 'UND_ERR_CONNECT_TIMEOUT' } }

Expected Behavior

The timeout error SHOULD RESPECT WHAT IS SPECIFIED, whether via the Undici.Agent or AbortSignal

[cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 20000ms)

Logs & Screenshots

console.logs:
Login error: TypeError: fetch failed at node:internal/deps/undici/undici:13502:13 at processTicksAndRejections (node:internal/process/task_queues:105:5) at async authenticateUser (C:\path\to\myApp\api-app\src\services\keycloak.ts:42:22) at async C:\path\to\myApp\api-app\src\routes\auth.ts:10:23 { [cause]: ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 10000ms) at onConnectTimeout (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:912:19) at Immediate._onImmediate (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:863:35) at processImmediate (node:internal/timers:491:21) { code: 'UND_ERR_CONNECT_TIMEOUT' } }

Environment

Node.js: 22.1.0
Undici: ^6.15.0 ?? (whatever come with Node 22.x)
OS: Windows 11

Additional context

Using undici.request() directly does respect connectTimeout and works perfectly:

import { request, Agent as UndiciAgent } from 'undici';

const undiciAgent = new UndiciAgent({
  connectTimeout: 20000, // Works as expected
  keepAliveTimeout: 1
});

const { statusCode, body } = await request('http://10.2.2.164:80/realms/dev/protocol/openid-connect/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({ /* ... */ }).toString(),
  dispatcher: undiciAgent, // This is honored
});

console.logs:
Login error: ConnectTimeoutError: Connect Timeout Error (attempted address: 10.2.2.164:80, timeout: 20000ms) at onConnectTimeout (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:912:19) at Immediate._onImmediate (C:\path\to\myApp\api-app\node_modules\undici\lib\core\util.js:863:35) at processImmediate (node:internal/timers:491:21) { code: 'UND_ERR_CONNECT_TIMEOUT' }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions