-
-
Notifications
You must be signed in to change notification settings - Fork 663
Description
Bug Description
When issuing an HTTP request to an unresponsive host with undici
and aborting it via AbortController
before the library’s timeout elapses, the request rejects as expected, but the Node.js process remains alive until the original timeout completes. With no other work pending, the process should exit promptly after the abort.
Reproducible By
Use the following minimal script as test.mjs
:
import {fetch} from "undici";
const url = "http://1.2.4.5:6789/"; // no server expected
const controller = new AbortController();
setTimeout(() => {
console.log(new Date().toISOString(), "aborting");
controller.abort();
}, 1000).unref();
fetch(url, {signal: controller.signal})
.catch(() => {})
.then(() => {
console.log(new Date().toISOString(), "fetch finished");
});
Then run with a wrapper to show process lifetime:
printf '%s before\n' "$(date -uIs)"; node test.mjs; printf '%s after\n' "$(date -uIs)"
Observed result: the request is aborted quickly, but the process does not exit until around the default connect/overall timeout.
Expected Behavior
After AbortController.abort()
causes the fetch
to reject, and with no other referenced timers/handles, the process should exit immediately (or very shortly thereafter).
Logs & Screenshots
2025-08-12T10:56:55+00:00 before
2025-08-12T10:56:56.412Z aborting
2025-08-12T10:56:56.416Z fetch finished
2025-08-12T10:57:05+00:00 after
Note: “after” prints ~10s after the request was aborted/settled, suggesting an internal referenced timer/handle remains until timeout expiry.
Environment
- OS: Linux 6.12.36
- Node.js: v22.13.1
- undici: 7.13.0
Additional context
It appears an internal connect/overall timeout or connection attempt remains referenced after abort, keeping the event loop alive until timeout expiry.