denoland/deno · error · RangeError
outgoingHighWaterMark cannot be negative
Error message
outgoingHighWaterMark cannot be negative
What it means
WebTransportDatagramDuplexStream.outgoingHighWaterMark sizes the buffer/queue threshold for outgoing datagrams. Its setter in ext/web/webtransport.js takes an 'unrestricted double' and throws a RangeError when assigned a negative value or NaN. As with the incoming variant, values below 1 are clamped to 1 rather than erroring.
Source
Thrown at ext/web/webtransport.js:857
throw new RangeError("incomingHighWaterMark cannot be negative");
}
if (value < 1) value = 1;
this.#incomingHighWaterMark = value;
}
get outgoingHighWaterMark() {
webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);
return this.#outgoingHighWaterMark;
}
set outgoingHighWaterMark(value) {
webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);
value = webidl.converters["unrestricted double"](
value,
"Failed to execute 'outgoingHighWaterMark' on 'WebTransportDatagramDuplexStream'",
);
if (value < 0 || NumberIsNaN(value)) {
throw new RangeError("outgoingHighWaterMark cannot be negative");
}
if (value < 1) value = 1;
this.#outgoingHighWaterMark = value;
}
get maxDatagramSize() {
webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);
if (this.#conn) {
return this.#conn.maxDatagramSize - this.#sessionIdBuf.length;
}
return 1024;
}
get readable() {
webidl.assertBranded(this, WebTransportDatagramDuplexStreamPrototype);
if (!this.#readable) {
this.#readable = new ReadableStream({
type: "bytes",View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Set a positive finite number appropriate for your datagram burst size.
- Replace negative sentinels with a real default before assignment.
- Validate with Number.isFinite(v) && v >= 0 first.
- Remember 0 is clamped to 1 — use a meaningful positive value instead.
Example fix
// before duplex.outgoingHighWaterMark = size; // size can be -1 from config // after duplex.outgoingHighWaterMark = Number.isFinite(size) && size >= 1 ? size : 1;
Defensive patterns
Strategy: validation
Validate before calling
function toHighWaterMark(v, fallback = 1) {
return Number.isFinite(v) && v >= 1 ? v : fallback;
}
duplex.outgoingHighWaterMark = toHighWaterMark(cfg.outHwm); Type guard
function isValidHighWaterMark(v) {
return typeof v === "number" && Number.isFinite(v) && v >= 0;
} Try / catch
try { duplex.outgoingHighWaterMark = v; } catch (e) { if (e instanceof RangeError) duplex.outgoingHighWaterMark = 1; else throw e; } Prevention
- Reject or clamp buffer-size config before it reaches the setter.
- Do not reuse '0/-1 means default' conventions from other transports.
- Keep all datagram tuning assignments behind one validated helper.
When it happens
Trigger: duplex.outgoingHighWaterMark = -1; NaN from math on undefined inputs; user-provided buffer sizes forwarded without validation.
Common situations: Performance-tuning knobs copied from other transports where 0 or -1 means 'default'; config reload paths assigning raw values; dividing by a variable that can be 0 producing Infinity-like or NaN edge cases.
Related errors
- incomingHighWaterMark cannot be negative
- incomingMaxAge cannot be negative
- outgoingMaxAge cannot be negative
- ERR_INVALID_ARG_VALUE
- BenchContext::start() has already been invoked
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/2fd9be34f39e5473.
Report an issue: GitHub.