denoland/deno · error · TypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "${name}" argument must be an instance of AbortSignal. Received ${signal}

What it means

stream.addAbortSignal(signal, stream) validates its first argument before wiring abort behavior. The polyfill's validator accepts any object that has an 'aborted' property (a deliberate duck-type check shared with readable-stream), and throws ERR_INVALID_ARG_TYPE for anything else: undefined, null, primitives, or plain objects. The thrown name in the message is the literal argument name 'signal'.

Source

Thrown at ext/node/polyfills/internal/streams/add-abort-signal.js:39

    ERR_INVALID_ARG_TYPE,
  },
} = imported1;

const {
  SymbolDispose,
} = primordials;

let addAbortListener;

// This method is inlined here for readable-stream
// It also does not allow for signal to not exist on the stream
// https://github.com/nodejs/node/pull/36061#discussion_r533718029
const validateAbortSignal = (signal, name) => {
  if (
    typeof signal !== "object" ||
    !("aborted" in signal)
  ) {
    throw new ERR_INVALID_ARG_TYPE(name, "AbortSignal", signal);
  }
};

const addAbortSignal = function addAbortSignal(signal, stream) {
  validateAbortSignal(signal, "signal");
  if (!isNodeStream(stream) && !isWebStream(stream)) {
    throw new ERR_INVALID_ARG_TYPE("stream", [
      "ReadableStream",
      "WritableStream",
      "Stream",
    ], stream);
  }
  return addAbortSignalNoValidate(signal, stream);
};

const addAbortSignalNoValidate = function (signal, stream) {
  if (typeof signal !== "object" || !("aborted" in signal)) {
    return stream;

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Default the signal: addAbortSignal(opts.signal ?? new AbortController().signal, stream), or skip the call when no signal exists
  2. Pass controller.signal, never the AbortController instance
  3. Guard before calling: if (signal && typeof signal === 'object' && 'aborted' in signal) addAbortSignal(signal, stream)

Example fix

// before
function handler(readable, opts = {}) {
  addAbortSignal(opts.signal, readable); // throws when opts.signal is undefined
}

// after
function handler(readable, opts = {}) {
  if (opts.signal) addAbortSignal(opts.signal, readable);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (opts.signal) addAbortSignal(opts.signal, stream);

Type guard

function isAbortSignalLike(s) {
  return typeof s === 'object' && s !== null && 'aborted' in s;
}

Prevention

When it happens

Trigger: stream.addAbortSignal(undefined, readable) - typically forwarding an optional opts.signal that was never supplied; addAbortSignal(abortController, stream) - passing the controller instead of controller.signal; addAbortSignal('SIGTERM', stream) or any primitive; passing a custom EventEmitter that lacks an 'aborted' property.

Common situations: Optional abort support where the signal parameter defaults to undefined; refactoring code that previously used its own listener wiring; passing a DOM AbortController object rather than its .signal; test harnesses calling addAbortSignal with mock objects that forget the aborted flag.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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