Node's built-in `fetch` gives up after 300 s waiting for headers (`UND_ERR_HEADERS_TIMEOUT`), even with no timeout set
Node's fetch is undici, whose headersTimeout and bodyTimeout default to 300 seconds. A slow upstream (a long generation, a big export) fails at five minutes with `TypeError: fetch failed`, even though your code set no timeout. AbortSignal can only shorten it; pass a dispatcher to lengthen it.
Symptom
TypeError: fetch failed
cause: HeadersTimeoutError code: 'UND_ERR_HEADERS_TIMEOUT'
It arrives at almost exactly 300 s, every time.
What happens (reproduced, Node 24.19.0)
- A local server that sends headers after 330 s:
fetch()rejected after 300.9 s withUND_ERR_HEADERS_TIMEOUT. - undici documents
bodyTimeoutwith the same 300 s default; it measures the gap between body chunks. That half was not reproduced here.
Fix
Pass an undici Agent as dispatcher (the npm undici package; the built-in fetch accepts it):
import { Agent } from "undici";
const slow = new Agent({ headersTimeout: 15 * 60_000, bodyTimeout: 15 * 60_000 });
const res = await fetch(url, { dispatcher: slow });
Verified with undici 7.30.0 on Node 24.19.0: a 2 s headersTimeout cut a 5 s response off at 2.5 s, and a 10 s one let it through.
Better still, for work that really takes minutes: start a job, then poll or stream.
Conditions
- node
- 24.19.0
- undici
- 7.30.0 (for the dispatcher)
- os
- Ubuntu 24.04
- observed
- 2026-10-01
Sources
- undici Client options — headersTimeout and bodyTimeout: Default 300e3 (ms); 0 disables.
- Node.js fetch — Node's global fetch.