denoland/deno · error · ERR_ILLEGAL_CONSTRUCTOR

ERR_ILLEGAL_CONSTRUCTOR

ERR_ILLEGAL_CONSTRUCTOR

Error message

Illegal constructor

What it means

The Histogram class exported from node:perf_hooks is intentionally not user-constructable: its constructor needs an internal handle and throws ERR_ILLEGAL_CONSTRUCTOR when handle === undefined (i.e. any external `new` call). Histogram instances are only meant to be obtained from monitorEventLoopDelay() or createHistogram().

Source

Thrown at ext/node/polyfills/perf_hooks.js:325

function getHistogramCloneId(histogram) {
  if (histogram[_cloneId] === undefined) {
    histogram[_cloneId] = nextHistogramCloneId++;
  }
  MapPrototypeSet(
    histogramCloneRegistry,
    histogram[_cloneId],
    histogram[_handle],
  );
  return histogram[_cloneId];
}

// Public, JS-side Histogram class - `instanceof` works against both
// `monitorEventLoopDelay()` results and `createHistogram()` results.
class Histogram {
  constructor(handle) {
    // Intentionally not user-constructable.
    if (handle === undefined) {
      throw new ERR_ILLEGAL_CONSTRUCTOR();
    }
    this[_handle] = handle;
  }

  get count() {
    return this[_handle].count;
  }
  get countBigInt() {
    return this[_handle].countBigInt;
  }
  get min() {
    if (this.max === 0) return EMPTY_HISTOGRAM_MIN;
    return this[_handle].min;
  }
  get minBigInt() {
    if (this.max === 0) return EMPTY_HISTOGRAM_MIN_BIGINT;
    return BigInt(this[_handle].minBigInt);
  }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Get instances from factories: perf_hooks.createHistogram() or perf_hooks.monitorEventLoopDelay()
  2. For tests, create a real histogram via createHistogram() and record() synthetic values into it
  3. Replace subclassing with composition: wrap a real histogram instance instead of extending Histogram

Example fix

// before
const h = new perf_hooks.Histogram();

// after
const { createHistogram } = require("node:perf_hooks");
const h = createHistogram();
Defensive patterns

Strategy: validation

Validate before calling

const { createHistogram } = require("node:perf_hooks");
const h = createHistogram(); // factories only — never `new Histogram()`

Type guard

const RecordableHistogram = require("node:perf_hooks").createHistogram().constructor;
const isHistogramInstance = (v) => v instanceof RecordableHistogram;

Try / catch

try {
  const h = new perf_hooks.Histogram();
} catch (err) {
  if (err.code === "ERR_ILLEGAL_CONSTRUCTOR") {
    h = perf_hooks.createHistogram();
  } else throw err;
}

Prevention

When it happens

Trigger: new perf_hooks.Histogram(); new (require("perf_hooks")).Histogram(); subclassing with class MyH extends perf_hooks.Histogram { constructor() { super(); } } — the subclass path also hits the undefined-handle branch.

Common situations: Trying to fabricate a histogram for tests or seeding; adapting older blog samples referencing internal IntervalHistogram; TypeScript code instantiating the exported type directly.

Related errors


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