denoland/deno · error · TypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "signal" argument must be an instance of AbortSignal. Received undefined

What it means

util.aborted(signal, resource) resolves when an AbortSignal fires, and requires signal to be defined. Deno's polyfill checks signal === undefined first and throws ERR_INVALID_ARG_TYPE, matching Node: an omitted signal would create a listener that never fires and silently leak the resource reference.

Source

Thrown at ext/node/polyfills/util.ts:280

      deprecated.prototype = fn.prototype;
    }

    ObjectDefineProperty(deprecated, "length", {
      __proto__: null,
      ...ObjectGetOwnPropertyDescriptor(fn, "length"),
    });
  }

  return deprecated;
}

// deno-lint-ignore require-await
async function aborted(
  signal,
  resource,
) {
  if (signal === undefined) {
    throw new ERR_INVALID_ARG_TYPE("signal", "AbortSignal", signal);
  }
  validateAbortSignal(signal, "signal");
  validateObject(resource, "resource", {
    allowArray: true,
    allowFunction: true,
  });
  if (signal.aborted) {
    return PromiseResolve();
  }
  const abortPromise = PromiseWithResolvers();
  const resourceRef = new SafeWeakRef(resource);
  const algorithm = () => {
    abortedRegistry.unregister(algorithm);
    if (WeakRefPrototypeDeref(resourceRef) !== undefined) {
      abortPromise.resolve();
    }
  };
  signal[abortSignal.add](algorithm);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Create an AbortController and pass its signal: util.aborted(controller.signal, resource).
  2. Default the parameter at the call site: util.aborted(signal ?? new AbortController().signal, resource).
  3. If that code path is not abortable, skip the util.aborted() call instead of passing undefined.

Example fix

// before
const ctrl = mayAbort ? new AbortController() : null;
await util.aborted(ctrl?.signal, resource); // ctrl null -> signal undefined -> throws

// after
const ctrl = new AbortController();
await util.aborted(ctrl.signal, resource);
Defensive patterns

Strategy: validation

Validate before calling

import { types } from "node:util";

function requireSignal(signal) {
  if (!types.isAbortSignal(signal)) {
    throw new TypeError("signal must be an AbortSignal");
  }
  return signal;
}
// util.aborted(requireSignal(signal), resource)

Type guard

function isAbortSignal(v) {
  return typeof v === "object" && v !== null &&
    typeof v.aborted === "boolean" &&
    typeof v.addEventListener === "function";
}

Prevention

When it happens

Trigger: Calling util.aborted() with no arguments or with undefined as the signal — commonly aborted(options?.signal, resource) where the options field was never set.

Common situations: Optional signals destructured from config objects that were never populated; porting code where the AbortController lived elsewhere and the wiring was lost; calling aborted() before the controller exists.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/96e9563d917206ed. Report an issue: GitHub.