denoland/deno · error · NodeRangeError

ERR_HTTP2_INVALID_SETTING_VALUE

ERR_HTTP2_INVALID_SETTING_VALUE

Error message

Invalid value for setting "Range Error": ${nsetting}

What it means

While packing session settings, http2/util.ts validates each customSettings entry: the setting identifier (the object key, coerced with Number()) must be a numeric value in 1..0xffff. A key that is not numeric, NaN, <= 0, or > 0xffff throws ERR_HTTP2_INVALID_SETTING_VALUE (RangeError variant) with the offending identifier in the message. customSettings keys are numeric HTTP/2 setting IDs, never names.

Source

Thrown at ext/node/polyfills/internal/http2/util.ts:402

function updateSettingsBuffer(settings) {
  ensureHttpStateBuffers();
  let flags = 0;
  let numCustomSettings = 0;

  if (typeof settings.customSettings === "object") {
    const customSettings = settings.customSettings;
    for (const setting in customSettings) {
      const val = customSettings[setting];
      if (typeof val === "number") {
        let set = false;
        const nsetting = Number(setting);
        if (
          NumberIsNaN(nsetting) ||
          typeof nsetting !== "number" ||
          0 >= nsetting ||
          nsetting > 0xffff
        ) {
          throw new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError(
            "Range Error",
            nsetting,
            0,
            0xffff,
          );
        }
        if (
          NumberIsNaN(val) ||
          typeof val !== "number" ||
          0 >= val ||
          val > 0xffffffff
        ) {
          throw new ERR_HTTP2_INVALID_SETTING_VALUE.RangeError(
            "Range Error",
            val,
            0,
            0xffffffff,
          );

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use numeric keys in 1-65535: customSettings: { 0xff02: 1 } — write them as numbers, not names
  2. Use http2.constants / documented IDs for known experimental settings
  3. Validate keys before connect: Number(key) is an integer within 1..65535

Example fix

// before
http2.connect("https://example.com", {
  settings: { customSettings: { enableFoo: 1 } }, // key -> NaN -> throw
});

// after
http2.connect("https://example.com", {
  settings: { customSettings: { 65278: 1 } }, // numeric setting id
});
Defensive patterns

Strategy: validation

Validate before calling

function validCustomSettingIds(cs = {}) {
  return Object.keys(cs).every((k) => {
    const id = Number(k);
    return Number.isInteger(id) && id >= 1 && id <= 0xffff;
  });
}
if (validCustomSettingIds(settings.customSettings)) {
  session = http2.connect(url, { settings });
}

Type guard

function isCustomSettingsMap(
  cs: unknown,
): cs is Record<number, number> {
  if (cs == null) return true;
  return Object.entries(cs).every(([k, v]) => {
    const id = Number(k);
    return Number.isInteger(id) && id >= 1 && id <= 0xffff &&
      Number.isFinite(v as number) && (v as number) >= 1 &&
      (v as number) <= 0xffffffff;
  });
}

Try / catch

try {
  session = http2.connect(url, { settings });
} catch (err) {
  if (err.code === "ERR_HTTP2_INVALID_SETTING_VALUE") {
    delete settings.customSettings; // drop bad ids and retry with standard settings
    session = http2.connect(url, { settings });
  } else throw err;
}

Prevention

When it happens

Trigger: http2.connect(url, { settings: { customSettings: { enableFoo: 1 } } }) — key 'enableFoo' coerces to NaN; { '0': 1 } (zero rejected); { '70000': 1 } (> 0xffff); float keys like '1.5'.

Common situations: Copied snippets using descriptive string names for experimental settings; porting nghttp2 numeric constants as strings that overflow; assuming any object key works because TypeScript types it as Record<string, number>.

Related errors


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