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

  1. Pass a non-negative finite number (0 is valid) or omit highWaterMark entirely to take the default
  2. Clamp computed values: highWaterMark: Math.max(0, Number(value) || 0)
  3. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/73d515f200b64498. Report an issue: GitHub.