denoland/deno · error · TypeError

Cannot construct PerformanceMark: startTime cannot be negati

Error message

Cannot construct PerformanceMark: startTime cannot be negative, received ${startTime}

What it means

The PerformanceMark constructor validates startTime after initializing the entry and throws TypeError `Cannot construct PerformanceMark: startTime cannot be negative, received <startTime>` for negative values (ext/web/15_performance.js:293-297). When omitted, startTime defaults to performance.now(), which is always non-negative.

Source

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

    options = { __proto__: null },
  ) {
    const prefix = "Failed to construct 'PerformanceMark'";
    webidl.requiredArguments(arguments.length, 1, prefix);

    name = webidl.converters.DOMString(name, prefix, "Argument 1");

    options = webidl.converters.PerformanceMarkOptions(
      options,
      prefix,
      "Argument 2",
    );

    const { detail = null, startTime = now() } = options;

    super(name, "mark", startTime, 0, illegalConstructorKey);
    this[webidl.brand] = webidl.brand;
    if (startTime < 0) {
      throw new TypeError(
        `Cannot construct PerformanceMark: startTime cannot be negative, received ${startTime}`,
      );
    }
    this[_detail] = getStructuredClone()(detail);
  }

  toJSON() {
    webidl.assertBranded(this, PerformanceMarkPrototype);
    return {
      name: this.name,
      entryType: this.entryType,
      startTime: this.startTime,
      duration: this.duration,
      detail: this.detail,
    };
  }

  [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Clamp: `{ startTime: Math.max(0, ts) }` or omit startTime to default to now.
  2. Fix the subtraction order so the value is a non-negative elapsed time.
  3. Prefer `performance.mark(name)` unless you need historical timestamps.

Example fix

// before
const m = new PerformanceMark("checkpoint", { startTime: t0 - t1 });

// after
const m = new PerformanceMark("checkpoint", { startTime: Math.max(0, t0 - t1) });
Defensive patterns

Strategy: validation

Validate before calling

const isNonNegativeNumber = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
const startTime = isNonNegativeNumber(rawTs) ? rawTs : performance.now();
const m = new PerformanceMark("checkpoint", { startTime });

Type guard

const isNonNegativeTimestamp = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;

Prevention

When it happens

Trigger: `new PerformanceMark('m', { startTime: -1 })`; passing a computed delta that happens to be negative (e.g. `t0 - t1` with operands swapped).

Common situations: Porting Node's performance.mark(name, { startTime }) with relative times; benchmark code subtracting baselines incorrectly; hand-building PerformanceEntry objects instead of using performance.mark().

Related errors


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