denoland/deno · error · TypeError

Failed to execute 'observe' on 'PerformanceObserver': Cannot

Error message

Failed to execute 'observe' on 'PerformanceObserver': Cannot specify both 'entryTypes' and 'type'.

What it means

PerformanceObserver.observe() accepts exactly one way to select entries: the legacy `entryTypes` array or the newer `type` string (added for buffered entry observation). The Web Performance API forbids passing both in the same options object, and Deno enforces this in ext/web/15_performance.js before any other validation. Deno's supported entry types are only "mark" and "measure". The error is a TypeError thrown synchronously from observe().

Source

Thrown at ext/web/15_performance.js:512

    }
    this[webidl.brand] = webidl.brand;
    this[_callback] = callback;
  }

  observe(options = { __proto__: null }) {
    webidl.assertBranded(this, PerformanceObserverPrototype);
    const prefix = "Failed to execute 'observe' on 'PerformanceObserver'";

    if (options === undefined || options === null) {
      throw new TypeError(
        `${prefix}: 1 argument required, but only 0 present.`,
      );
    }

    const { entryTypes, type } = options;

    if (entryTypes !== undefined && type !== undefined) {
      throw new TypeError(
        `${prefix}: Cannot specify both 'entryTypes' and 'type'.`,
      );
    }

    if (entryTypes === undefined && type === undefined) {
      throw new TypeError(
        `${prefix}: Either 'entryTypes' or 'type' must be specified.`,
      );
    }

    let types;
    if (entryTypes !== undefined) {
      if (!ArrayIsArray(entryTypes)) {
        throw new TypeError(`${prefix}: 'entryTypes' must be an array.`);
      }
      types = ArrayPrototypeFilter(
        entryTypes,
        (t) =>

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Delete one of the two keys so the options object has either entryTypes or type, never both.
  2. For observing a single kind of entry, keep `type` and drop entryTypes, e.g. observe({ type: "mark", buffered: true }).
  3. For observing several kinds, keep the array form: observe({ entryTypes: ["mark", "measure"] }).
  4. If you build options dynamically, filter keys before passing: only allow one of entryTypes/type through.

Example fix

// before
observer.observe({ entryTypes: ["mark", "measure"], type: "mark" });

// after
observer.observe({ entryTypes: ["mark", "measure"] });
// or, single-type form:
observer.observe({ type: "mark", buffered: true });
Defensive patterns

Strategy: validation

Validate before calling

function safeObserve(observer, options) {
  const hasEntry = "entryTypes" in options;
  const hasType = "type" in options;
  if (hasEntry && hasType) {
    throw new Error("Pass either entryTypes or type, not both");
  }
  if (!hasEntry && !hasType) {
    throw new Error("Pass one of entryTypes or type");
  }
  observer.observe(options);
}

Type guard

function isObserveOptions(o) {
  const hasEntry = o != null && "entryTypes" in o;
  const hasType = o != null && "type" in o;
  return hasEntry !== hasType; // exactly one
}

Try / catch

try { observer.observe(opts); } catch (e) { if (e instanceof TypeError && e.message.includes("entryTypes")) fixOptions(); else throw e; }

Prevention

When it happens

Trigger: Calling `new PerformanceObserver(cb).observe({ entryTypes: ["mark"], type: "measure" })`; copying code that merged an entryTypes-based snippet with a type-based snippet; spreading a defaults object that already contains entryTypes and then adding type.

Common situations: Migrating from the deprecated entryTypes API to the type API and leaving the old key behind; combining options objects via object spread where one contributor supplies entryTypes and another supplies type; adapting browser examples (resource, navigation, longtask types) that were partly rewritten for Deno.

Related errors


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