denoland/deno · error · TypeError

Illegal constructor

Error message

Illegal constructor

What it means

AbortSignal's constructor is gated by an internal illegalConstructorKey symbol (ext/web/03_abort_signal.js:225-229): new AbortSignal() (or instantiating a subclass, since the default key parameter never matches) throws TypeError 'Illegal constructor'. Signals are meant to come from factories — new AbortController().signal, AbortSignal.timeout(), AbortSignal.abort(), AbortSignal.any() — and the assertBranded getters pair with this guard to keep internal slots unforgeable.

Source

Thrown at ext/web/03_abort_signal.js:225

    // release strong references from source signals now that abort has been delivered
    if (this[sourceSignals] !== null) {
      for (const weakRef of new SafeSetIterator(this[sourceSignals])) {
        const sourceSignal = WeakRefPrototypeDeref(weakRef);
        if (sourceSignal !== undefined && sourceSignal[activeDependents]) {
          SetPrototypeDelete(sourceSignal[activeDependents], this);
        }
      }
    }
  }

  [remove](algorithm) {
    this[abortAlgos] && SetPrototypeDelete(this[abortAlgos], algorithm);
  }

  constructor(key = null) {
    if (key !== illegalConstructorKey) {
      throw new TypeError("Illegal constructor");
    }
    super();
  }

  get aborted() {
    webidl.assertBranded(this, AbortSignalPrototype);
    return this[abortReason] !== undefined;
  }

  get reason() {
    webidl.assertBranded(this, AbortSignalPrototype);
    return this[abortReason];
  }

  throwIfAborted() {
    webidl.assertBranded(this, AbortSignalPrototype);
    if (this[abortReason] !== undefined) {
      throw this[abortReason];

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Create signals via factories: new AbortController().signal for controllable signals, AbortSignal.timeout(ms) for deadlines, AbortSignal.abort(reason) for pre-aborted, AbortSignal.any([...]) for composition.
  2. Type variables as AbortSignal and construct them only through these APIs.
  3. Do not subclass AbortSignal — compose behavior with AbortSignal.any or by listening to abort events.

Example fix

// before
const signal = new AbortSignal(); // TypeError: Illegal constructor

// after
const signal = AbortSignal.timeout(5_000); // or new AbortController().signal
Defensive patterns

Strategy: fallback

Validate before calling

const signal = opts?.signal instanceof AbortSignal
  ? opts.signal
  : AbortSignal.any([AbortSignal.timeout(5_000)]);

Type guard

const isAbortSignal = (v) => v instanceof AbortSignal;

Prevention

When it happens

Trigger: new AbortSignal(); class TimedSignal extends AbortSignal {} followed by new TimedSignal(); Reflect.construct(AbortSignal, []).

Common situations: TypeScript users writing new AbortSignal() as a placeholder; test helpers trying to fabricate pre-aborted signals; copy-pasted snippets that assume a constructible signal; polyfills from other runtimes where signals were emulated with classes.

Related errors


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