denoland/deno · error · TypeError
Options cannot be passed with "endMark"
Error message
Options cannot be passed with "endMark"
What it means
performance.measure(name, startOrMeasureOptions, endMark) has two mutually exclusive shapes: either a third-argument endMark string, or a second-argument options object describing start/end/duration. Deno throws a TypeError from ext/web/15_performance.js when the options object is a non-empty object AND an endMark string was also passed. The check only fires for real objects with at least one own key.
Source
Thrown at ext/web/15_performance.js:754
);
startOrMeasureOptions = webidl.converters
["DOMString or PerformanceMeasureOptions"](
startOrMeasureOptions,
prefix,
"Argument 2",
);
if (endMark !== undefined) {
endMark = webidl.converters.DOMString(endMark, prefix, "Argument 3");
}
if (
startOrMeasureOptions && typeof startOrMeasureOptions === "object" &&
ObjectKeys(startOrMeasureOptions).length > 0
) {
if (endMark) {
throw new TypeError('Options cannot be passed with "endMark"');
}
if (
ReflectHas(startOrMeasureOptions, "start") &&
ReflectHas(startOrMeasureOptions, "duration") &&
ReflectHas(startOrMeasureOptions, "end")
) {
throw new TypeError(
'Cannot specify "start", "end", and "duration" together in options',
);
}
}
let endTime;
if (endMark) {
endTime = convertMarkToTimestamp(endMark);
} else if (
typeof startOrMeasureOptions === "object" &&
ReflectHas(startOrMeasureOptions, "end")
) {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pick one shape: use endMark as argument 3 with at most a start mark/number as argument 2, or put everything in the options object.
- To express start-to-end, prefer options: performance.measure("m", { start: "mark1", end: "mark2" }).
- If argument 2 is only a start mark name, that is fine with endMark — the conflict is only with a non-empty options object.
- In wrapper functions, branch: if the caller supplied options, ignore/forbid endMark.
Example fix
// before
performance.measure("m", { start: "a" }, "b");
// after
performance.measure("m", { start: "a", end: "b" }); Defensive patterns
Strategy: validation
Validate before calling
function measure(name, options, endMark) {
const hasOptions =
options != null && typeof options === "object" &&
Object.keys(options).length > 0;
if (hasOptions && endMark !== undefined) {
// move endMark into options instead of throwing
options = { ...options, end: endMark };
endMark = undefined;
}
return performance.measure(name, options, endMark);
} Type guard
function isMeasureOptions(v) {
return v != null && typeof v === "object" && !Array.isArray(v);
} Try / catch
try { performance.measure(n, opts, endMark); } catch (e) { if (e instanceof TypeError && e.message.includes("endMark")) performance.measure(n, { ...opts, end: endMark }); else throw e; } Prevention
- In wrappers, choose one calling convention and document it.
- Do not forward both parameters blindly from a generic helper.
- Prefer the options object form for new code; it expresses everything endMark can.
When it happens
Trigger: performance.measure("m", { start: 0 }, "endMark") — options plus a mark name; passing a default empty-ish options object that later gained keys; wrapper functions that accept both parameters and forward them unconditionally.
Common situations: Generalizing a measure() helper so it accepts options and endMark, then calling it with both; refactoring from the (startMark, endMark) form to the options form without removing the third argument; copy-pasting from mixed examples.
Related errors
- Cannot specify "start", "end", and "duration" together in op
- Failed to execute 'observe' on 'PerformanceObserver': Cannot
- Failed to execute 'observe' on 'PerformanceObserver': Either
- Failed to execute 'observe' on 'PerformanceObserver': 'entry
- Cannot construct PerformanceMark: startTime cannot be negati
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/d1166c8d73b41a10.
Report an issue: GitHub.