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
- Clamp: `{ startTime: Math.max(0, ts) }` or omit startTime to default to now.
- Fix the subtraction order so the value is a non-negative elapsed time.
- 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
- Clamp or omit startTime; the default is performance.now(), which is always valid.
- Prefer performance.mark(name) unless historical timestamps are required.
- Double-check subtraction order when computing relative start times.
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
- Mark cannot be negative: received ${mark}
- Options cannot be passed with "endMark"
- Cannot specify "start", "end", and "duration" together in op
- BenchContext::start() has already been invoked
- ${prefix}Linter plugin name must only contain lowercase lett
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/5ff77548197d84eb.
Report an issue: GitHub.