nodejs / nodejs/undici

Process does not exit after aborting a request to an unresponsive host

Open
#4,405 4 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
JavaScript
Stars
7.7k
Forks
879
Avg merge
2d 16h
Merged PRs (30d)
68

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided test.mjs reproduction with undici's fetch and AbortController, then inspect the request abort and connect/overall timeout handling. The fix is complete when aborting the unresponsive-host request rejects promptly and the wrapper's process exits without waiting for the original timeout.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.