websockets/ws · error · Error

Unexpected parameter "client_no_context_takeover"

Error message

Unexpected parameter "client_no_context_takeover"

What it means

Thrown by `PerMessageDeflate.acceptAsClient()` when the client set `clientNoContextTakeover: false` (it does not want context takeover disabled on its side) but the server's permessage-deflate response nevertheless includes `client_no_context_takeover`. The client treats this as an unacceptable response and aborts negotiation.

Solutions

  1. Allow the client to accept context-takeover disabling by not setting `clientNoContextTakeover: false` (or setting it `true`).
  2. Relax the server policy so it does not force `client_no_context_takeover` on unwilling clients.
  3. Disable compression on the client with `perMessageDeflate: false` if the policy mismatch cannot be resolved.

Example fix

// before
const ws = new WebSocket(url, {
  perMessageDeflate: { clientNoContextTakeover: false }
});
// server responds with client_no_context_takeover -> throws

// after — allow takeover disabling
const ws = new WebSocket(url, {
  perMessageDeflate: { clientNoContextTakeover: true }
});
Defensive patterns

Strategy: try-catch

Try / catch

try {
  perMessageDeflate.accept(serverResponseOffers);
} catch (err) {
  if (/Unexpected parameter "client_no_context_takeover"/.test(err.message)) {
    // Server forced context-takeoff disabling that the client refused.
    // Either relax the client option or disable compression.
    reconnectWithoutCompression(url);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Client created with `new WebSocket(url, { perMessageDeflate: { clientNoContextTakeover: false } })` connecting to a server whose agreed response forces `client_no_context_takeover`. Surfaces during the client-side handshake.

Common situations: Server and client disagree on context takeover to save memory; a server policy that always disables takeover meets a client that requires it for performance; misconfigured reverse proxy that rewrites the extension response.

Related errors


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

Appendix: source

Thrown at lib/permessage-deflate.js:219

    return accepted;
  }

  /**
   * Accept the extension negotiation response.
   *
   * @param {Array} response The extension negotiation response
   * @return {Object} Accepted configuration
   * @private
   */
  acceptAsClient(response) {
    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;
  }

View on GitHub (pinned to c791e707ea)