denoland/deno · error · RangeError
ERR_INVALID_ARG_VALUE
ERR_INVALID_ARG_VALUE
Error message
The property 'strategy.highWaterMark' is invalid. Received ${inspected} What it means
Shared web-stream queuing-strategy validation in ext/node/polyfills/internal/webstreams/util.js, used by node:stream/web stream constructors and the node adapters. extractHighWaterMark coerces the value with unary + and requires the result to be a number that is not NaN and not negative; otherwise it throws ERR_INVALID_ARG_VALUE as a RangeError. Strings like '10' pass via coercion, while {} or 'abc' coerce to NaN and throw.
Source
Thrown at ext/node/polyfills/internal/webstreams/util.js:50
const webStreams = core.loadExtScript("ext:deno_web/06_streams.js");
const kState = webStreams.kNodeWebStreamsState;
const kType = webStreams.kNodeWebStreamsType;
const AsyncIterator = {
__proto__: Object.getPrototypeOf(
Object.getPrototypeOf(Object.getPrototypeOf((async function* () {})())),
),
next: undefined,
return: undefined,
};
function extractHighWaterMark(value, defaultHWM) {
if (value === undefined) return defaultHWM;
value = +value;
if (typeof value !== "number" || NumberIsNaN(value) || value < 0) {
throw new ERR_INVALID_ARG_VALUE.RangeError(
"strategy.highWaterMark",
value,
);
}
return value;
}
function extractSizeAlgorithm(size) {
if (size === undefined) return () => 1;
validateFunction(size, "strategy.size");
return size;
}
function customInspect(depth, options, name, data) {
if (depth < 0) return this;
const opts = {
...options,
depth: options.depth == null ? null : options.depth - 1,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass a non-negative finite number (0 is valid) or omit highWaterMark entirely to take the default
- Clamp computed values: highWaterMark: Math.max(0, Number(value) || 0)
- Pre-check with Number.isFinite(Number(value)) && Number(value) >= 0 before constructing the strategy
Example fix
// before
new ReadableStream(src, { highWaterMark: config.hwm }); // config.hwm = -1 or 'abc'
// after
const hwm = Number(config.hwm);
new ReadableStream(src, {
highWaterMark: Number.isFinite(hwm) && hwm >= 0 ? hwm : undefined,
}); Defensive patterns
Strategy: validation
Validate before calling
const hwm = Number(strategy?.highWaterMark);
const safeHwm = Number.isFinite(hwm) && hwm >= 0 ? hwm : undefined;
const rs = new ReadableStream(src, { ...strategy, highWaterMark: safeHwm }); Type guard
function isValidHighWaterMark(v: unknown): v is number {
const n = Number(v);
return typeof n === 'number' && !Number.isNaN(n) && n >= 0 && n !== Infinity || v === undefined;
} Prevention
- Clamp config-derived HWM: Math.max(0, Number(value) || 0)
- Treat 'not set' as undefined — never null, NaN, or an empty string
- Remember strings like '10' coerce successfully but objects and 'abc' become NaN
When it happens
Trigger: new ReadableStream(..., { highWaterMark: -1 }); { highWaterMark: NaN } from arithmetic on config values; { highWaterMark: 'abc' } or { highWaterMark: {} } which coerce to NaN; TransformStream(..., { highWaterMark: Number('auto') }).
Common situations: HWM computed from user config or environment variables that can be unset (NaN), zero-crossing math producing negatives, or porting code that passed strings/objects assuming strict validation would coerce them.
Related errors
- ERR_ARG_NOT_ITERABLE
- ERR_INVALID_STATE
- ${prefix}: When underlying source is "bytes", strategy.size
- incomingHighWaterMark cannot be negative
- outgoingHighWaterMark cannot be negative
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/73d515f200b64498.
Report an issue: GitHub.