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()` when the server's permessage-deflate response contains a `client_max_window_bits` value the client cannot accept: either the client set `clientMaxWindowBits: false` (it does not want this parameter) but the server sent one, or the server sent a value larger than the number the client advertised (`params.client_max_window_bits > clientMaxWindowBits`). RFC 7692 forbids the server from raising the window above the client's offer.

Solutions

  1. Match the client's `clientMaxWindowBits` to (or above) what the server will respond with, or omit it to advertise the default.
  2. Fix the server so it never responds with a `client_max_window_bits` larger than the client's offer.
  3. Disable compression on the client (`perMessageDeflate: false`) if the server cannot be changed.

Example fix

// before
const ws = new WebSocket(url, {
  perMessageDeflate: { clientMaxWindowBits: 10 }
});
// server responds with client_max_window_bits=15 -> throws

// after
const ws = new WebSocket(url, {
  perMessageDeflate: { clientMaxWindowBits: 15 }
});
Defensive patterns

Strategy: try-catch

Try / catch

try {
  perMessageDeflate.accept(serverResponseOffers);
} catch (err) {
  if (/client_max_window_bits/.test(err.message)) {
    // Server's window-size response is incompatible with the client's offer.
    reconnectWithoutCompression(url);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Client created with `new WebSocket(url, { perMessageDeflate: { clientMaxWindowBits: 10 } })` against a server that responds with `client_max_window_bits: 15`; or a client with `clientMaxWindowBits: false` against a server that includes the parameter anyway.

Common situations: Server bug/proxy that inflates the window size in the response; mismatched compression policies across a load balancer; a peer that does not honor RFC 7692 negotiation rules.

Related errors


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

Appendix: source

Thrown at lib/permessage-deflate.js:231

    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 c791e707ea)