websockets/ws · error · Error

Unknown parameter

Error message

Unknown parameter "${key}"

What it means

Thrown by `PerMessageDeflate.normalizeParams()` when a parameter key is not one of the four recognized permessage-deflate parameters (`client_max_window_bits`, `server_max_window_bits`, `client_no_context_takeover`, `server_no_context_takeover`). Any other key in the offer is rejected because RFC 7692 defines a closed set of parameters for this extension.

Solutions

  1. Restrict parameters to the four RFC 7692 keys listed above.
  2. If you are experimenting with custom parameters, fork or extend `normalizeParams`; the public API will not accept them.
  3. Catch the error during the handshake and close with code 1002.

Example fix

// before
pmd.normalizeParams([{ unknown_param: ['1'] }]);

// after — recognized parameter only
pmd.normalizeParams([{ server_max_window_bits: ['12'] }]);
Defensive patterns

Strategy: validation

Validate before calling

// Only the four RFC 7692 parameters are allowed.
const KNOWN_PMD_PARAMS = new Set([
  'client_max_window_bits',
  'server_max_window_bits',
  'client_no_context_takeover',
  'server_no_context_takeover'
]);
function hasUnknownParams(offer) {
  return Object.keys(offer).some((k) => !KNOWN_PMD_PARAMS.has(k));
}

Try / catch

try {
  perMessageDeflate.accept(parsedOffers);
} catch (err) {
  if (/Unknown parameter/.test(err.message)) {
    abortHandshake(socket, 1002);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: A peer sends `Sec-WebSocket-Extensions: permessage-deflate; foo=bar` (unknown parameter `foo`); `normalizeParams` (called from `accept()`) throws with the offending key interpolated.

Common situations: A peer advertises a vendor/non-standard parameter; a typo in a hand-built header; a future/unknown extension parameter the library does not recognize; fuzzer input.

Related errors


AI-assisted analysis of websockets/ws@c791e707ea (2026-08-06). Data as JSON: /api/errors/8a449514d3c08f6b. Report an issue: GitHub.

Appendix: source

Thrown at lib/permessage-deflate.js:289

        } else if (key === 'server_max_window_bits') {
          const num = +value;
          if (!Number.isInteger(num) || num < 8 || num > 15) {
            throw new TypeError(
              `Invalid value for parameter "${key}": ${value}`
            );
          }
          value = num;
        } else if (
          key === 'client_no_context_takeover' ||
          key === 'server_no_context_takeover'
        ) {
          if (value !== true) {
            throw new TypeError(
              `Invalid value for parameter "${key}": ${value}`
            );
          }
        } else {
          throw new Error(`Unknown parameter "${key}"`);
        }

        params[key] = value;
      });
    });

    return configurations;
  }

  /**
   * Decompress data. Concurrency limited.
   *
   * @param {Buffer} data Compressed data
   * @param {Boolean} fin Specifies whether or not this is the last fragment
   * @param {Function} callback Callback
   * @public
   */
  decompress(data, fin, callback) {

View on GitHub (pinned to c791e707ea)