{"record":{"id":"8094d239452b701b","repo":"denoland/deno","slug":"outgoingmaxage-cannot-be-negative","errorCode":null,"errorMessage":"outgoingMaxAge cannot be negative","messagePattern":"outgoingMaxAge cannot be negative","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ext/web/webtransport.js","lineNumber":821,"sourceCode":"      throw new RangeError(\"incomingMaxAge cannot be negative\");\n    }\n    if (value === 0) value = null;\n    this.#incomingMaxAge = value;\n  }\n\n  get outgoingMaxAge() {\n    webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);\n    return this.#outgoingMaxAge;\n  }\n\n  set outgoingMaxAge(value) {\n    webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);\n    value = webidl.converters[\"unrestricted double?\"](\n      value,\n      \"Failed to execute 'outgoingMaxAge' on 'WebTransportDatagramDuplexStream'\",\n    );\n    if (value < 0 || NumberIsNaN(value)) {\n      throw new RangeError(\"outgoingMaxAge cannot be negative\");\n    }\n    if (value === 0) value = null;\n    this.#outgoingMaxAge = value;\n  }\n\n  get incomingHighWaterMark() {\n    webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);\n    return this.#incomingHighWaterMark;\n  }\n\n  set incomingHighWaterMark(value) {\n    webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);\n    value = webidl.converters[\"unrestricted double\"](\n      value,\n      \"Failed to execute 'incomingHighWaterMark' on 'WebTransportDatagramDuplexStream'\",\n    );\n    if (value < 0 || NumberIsNaN(value)) {\n      throw new RangeError(\"incomingHighWaterMark cannot be negative\");","sourceCodeStart":803,"sourceCodeEnd":839,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/webtransport.js#L803-L839","documentation":"WebTransportDatagramDuplexStream.outgoingMaxAge sets a maximum age for outgoing datagrams on the sender side. Its setter in ext/web/webtransport.js takes an 'unrestricted double?' and throws a RangeError for negative values or NaN. Zero is converted to null, meaning no age limit is applied.","triggerScenarios":"duplex.outgoingMaxAge = -100; assigning NaN produced by arithmetic on undefined; forwarding a user-supplied TTL/config value without bounds-checking.","commonSituations":"Exposing maxAge configuration to users without validation; reusing '-1 means forever' conventions from other systems; computing age from timestamps where clock skew makes the result negative.","solutions":["Assign a non-negative millisecond value or null.","Clamp or reject user input before it reaches the setter.","Treat 'unset' as null, and note 0 behaves the same as null.","Check Number.isFinite before assigning any computed value."],"exampleFix":"// before\nduplex.outgoingMaxAge = ageHint; // ageHint may be -1 or NaN\n\n// after\nduplex.outgoingMaxAge =\n  Number.isFinite(ageHint) && ageHint > 0 ? ageHint : null;","handlingStrategy":"validation","validationCode":"function toMaxAge(v) {\n  return Number.isFinite(v) && v > 0 ? v : null;\n}\nduplex.outgoingMaxAge = toMaxAge(ttlMs);","typeGuard":"function isValidMaxAge(v) {\n  return v == null || (typeof v === \"number\" && Number.isFinite(v) && v >= 0);\n}","tryCatchPattern":"try { duplex.outgoingMaxAge = v; } catch (e) { if (e instanceof RangeError) duplex.outgoingMaxAge = null; else throw e; }","preventionTips":["Clamp user-supplied TTLs to positive numbers or null.","Do not forward raw config numbers straight to setters.","Treat 0 and null alike (both mean 'no age limit') in your config semantics."],"tags":["webtransport","datagrams","validation","rangeerror"],"backgroundTag":"negative-value-rejected","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}