{"record":{"id":"5ff77548197d84eb","repo":"denoland/deno","slug":"cannot-construct-performancemark-starttime-cannot","errorCode":null,"errorMessage":"Cannot construct PerformanceMark: startTime cannot be negative, received ${startTime}","messagePattern":"Cannot construct PerformanceMark: startTime cannot be negative, received (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/15_performance.js","lineNumber":293,"sourceCode":"    options = { __proto__: null },\n  ) {\n    const prefix = \"Failed to construct 'PerformanceMark'\";\n    webidl.requiredArguments(arguments.length, 1, prefix);\n\n    name = webidl.converters.DOMString(name, prefix, \"Argument 1\");\n\n    options = webidl.converters.PerformanceMarkOptions(\n      options,\n      prefix,\n      \"Argument 2\",\n    );\n\n    const { detail = null, startTime = now() } = options;\n\n    super(name, \"mark\", startTime, 0, illegalConstructorKey);\n    this[webidl.brand] = webidl.brand;\n    if (startTime < 0) {\n      throw new TypeError(\n        `Cannot construct PerformanceMark: startTime cannot be negative, received ${startTime}`,\n      );\n    }\n    this[_detail] = getStructuredClone()(detail);\n  }\n\n  toJSON() {\n    webidl.assertBranded(this, PerformanceMarkPrototype);\n    return {\n      name: this.name,\n      entryType: this.entryType,\n      startTime: this.startTime,\n      duration: this.duration,\n      detail: this.detail,\n    };\n  }\n\n  [SymbolFor(\"Deno.privateCustomInspect\")](inspect, inspectOptions) {","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/15_performance.js#L275-L311","documentation":"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.","triggerScenarios":"`new PerformanceMark('m', { startTime: -1 })`; passing a computed delta that happens to be negative (e.g. `t0 - t1` with operands swapped).","commonSituations":"Porting Node's performance.mark(name, { startTime }) with relative times; benchmark code subtracting baselines incorrectly; hand-building PerformanceEntry objects instead of using performance.mark().","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."],"exampleFix":"// before\nconst m = new PerformanceMark(\"checkpoint\", { startTime: t0 - t1 });\n\n// after\nconst m = new PerformanceMark(\"checkpoint\", { startTime: Math.max(0, t0 - t1) });","handlingStrategy":"validation","validationCode":"const isNonNegativeNumber = (v) => typeof v === \"number\" && Number.isFinite(v) && v >= 0;\nconst startTime = isNonNegativeNumber(rawTs) ? rawTs : performance.now();\nconst m = new PerformanceMark(\"checkpoint\", { startTime });","typeGuard":"const isNonNegativeTimestamp = (v) => typeof v === \"number\" && Number.isFinite(v) && v >= 0;","tryCatchPattern":null,"preventionTips":["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."],"tags":["performance","performance-mark","validation"],"backgroundTag":"performance-timestamp-invalid","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}