websockets/ws · error · Error

Unexpected or invalid parameter "client_max_window_bits"

Error message

Unexpected or invalid parameter "client_max_window_bits"

What it means

Thrown by PerMessageDeflate.acceptAsClient() (permessage-deflate.js:224-231) when the server's response contains a client_max_window_bits value that is unacceptable to the client. Two sub-conditions: (a) the client set clientMaxWindowBits to false (explicitly forbidding it) yet the server sent it, or (b) the client requested a specific number but the server's value exceeds it (server value > client's configured max).

Source

Thrown at lib/permessage-deflate.js:229

    const params = response[0];

    if (
      this._options.clientNoContextTakeover === false &&
      params.client_no_context_takeover
    ) {
      throw new Error('Unexpected parameter "client_no_context_takeover"');
    }

    if (!params.client_max_window_bits) {
      if (typeof this._options.clientMaxWindowBits === 'number') {
        params.client_max_window_bits = this._options.clientMaxWindowBits;
      }
    } else if (
      this._options.clientMaxWindowBits === false ||
      (typeof this._options.clientMaxWindowBits === 'number' &&
        params.client_max_window_bits > this._options.clientMaxWindowBits)
    ) {
      throw new Error(
        'Unexpected or invalid parameter "client_max_window_bits"'
      );
    }

    return params;
  }

  /**
   * Normalize parameters.
   *
   * @param {Array} configurations The extension negotiation offers/reponse
   * @return {Array} The offers/response with normalized parameters
   * @private
   */
  normalizeParams(configurations) {
    configurations.forEach((params) => {
      Object.keys(params).forEach((key) => {
        let value = params[key];

View on GitHub (pinned to ae1de54330)

Solutions

  1. Increase or remove the client's clientMaxWindowBits numeric cap so it is >= the server's offered value.
  2. If the client set clientMaxWindowBits: false, change it to true or remove it to permit the parameter.
  3. Reconfigure the server to not send a client_max_window_bits value that conflicts with the client's offer.
  4. Disable compression with perMessageDeflate: false if the two sides cannot agree.

Example fix

// before — client caps at 10, server offers 12
const ws = new WebSocket('ws://host', {
  perMessageDeflate: { clientMaxWindowBits: 10 }
});

// after — remove the cap or set it >= server's value
const ws = new WebSocket('ws://host', {
  perMessageDeflate: { clientMaxWindowBits: 12 }
});
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure clientMaxWindowBits is not false and is >= any expected server value
function validateWindowBitsOpts(opts) {
  if (!opts) return true;
  if (opts.clientMaxWindowBits === false) return false;
  if (typeof opts.clientMaxWindowBits === 'number' &&
      (opts.clientMaxWindowBits < 8 || opts.clientMaxWindowBits > 15)) return false;
  return true;
}

Try / catch

try {
  perMessageDeflate.accept(serverResponse);
} catch (err) {
  if (err.message.includes('client_max_window_bits')) {
    console.error('Server window-bits value incompatible:', err.message);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: A client with `{ perMessageDeflate: { clientMaxWindowBits: false } }` receives a server response containing client_max_window_bits. Or a client with `{ clientMaxWindowBits: 10 }` receives a server response with client_max_window_bits=12 (12 > 10). acceptAsClient() throws during the client-side accept() call.

Common situations: A client caps the window size for memory/performance but the server advertises a larger size. A client sets clientMaxWindowBits: false to forbid it, but a non-compliant server includes it anyway. Mismatched compression policy between client and server.

Related errors


AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03). Data as JSON: /data/errors/3698fc17f5af4f41.json. Report an issue: GitHub.