{"id":"3698fc17f5af4f41","repo":"websockets/ws","slug":"unexpected-or-invalid-parameter-client-max-window","errorCode":null,"errorMessage":"Unexpected or invalid parameter \"client_max_window_bits\"","messagePattern":"Unexpected or invalid parameter \"client_max_window_bits\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/permessage-deflate.js","lineNumber":229,"sourceCode":"    const params = response[0];\n\n    if (\n      this._options.clientNoContextTakeover === false &&\n      params.client_no_context_takeover\n    ) {\n      throw new Error('Unexpected parameter \"client_no_context_takeover\"');\n    }\n\n    if (!params.client_max_window_bits) {\n      if (typeof this._options.clientMaxWindowBits === 'number') {\n        params.client_max_window_bits = this._options.clientMaxWindowBits;\n      }\n    } else if (\n      this._options.clientMaxWindowBits === false ||\n      (typeof this._options.clientMaxWindowBits === 'number' &&\n        params.client_max_window_bits > this._options.clientMaxWindowBits)\n    ) {\n      throw new Error(\n        'Unexpected or invalid parameter \"client_max_window_bits\"'\n      );\n    }\n\n    return params;\n  }\n\n  /**\n   * Normalize parameters.\n   *\n   * @param {Array} configurations The extension negotiation offers/reponse\n   * @return {Array} The offers/response with normalized parameters\n   * @private\n   */\n  normalizeParams(configurations) {\n    configurations.forEach((params) => {\n      Object.keys(params).forEach((key) => {\n        let value = params[key];","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/websockets/ws/blob/ae1de54330cef77e487548890fabfeb9aae1d83d/lib/permessage-deflate.js#L211-L247","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Increase or remove the client's clientMaxWindowBits numeric cap so it is >= the server's offered value.","If the client set clientMaxWindowBits: false, change it to true or remove it to permit the parameter.","Reconfigure the server to not send a client_max_window_bits value that conflicts with the client's offer.","Disable compression with perMessageDeflate: false if the two sides cannot agree."],"exampleFix":"// before — client caps at 10, server offers 12\nconst ws = new WebSocket('ws://host', {\n  perMessageDeflate: { clientMaxWindowBits: 10 }\n});\n\n// after — remove the cap or set it >= server's value\nconst ws = new WebSocket('ws://host', {\n  perMessageDeflate: { clientMaxWindowBits: 12 }\n});","handlingStrategy":"try-catch","validationCode":"// Ensure clientMaxWindowBits is not false and is >= any expected server value\nfunction validateWindowBitsOpts(opts) {\n  if (!opts) return true;\n  if (opts.clientMaxWindowBits === false) return false;\n  if (typeof opts.clientMaxWindowBits === 'number' &&\n      (opts.clientMaxWindowBits < 8 || opts.clientMaxWindowBits > 15)) return false;\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  perMessageDeflate.accept(serverResponse);\n} catch (err) {\n  if (err.message.includes('client_max_window_bits')) {\n    console.error('Server window-bits value incompatible:', err.message);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Do not set clientMaxWindowBits: false unless you are certain the server will not send it.","If setting a numeric clientMaxWindowBits, ensure it is >= the value the server typically responds with.","Test against the specific server you are connecting to before restricting options.","Remember: omitting clientMaxWindowBits entirely is usually the safest default."],"tags":["websocket","permessage-deflate","compression","handshake","negotiation"],"analyzedSha":"ae1de54330cef77e487548890fabfeb9aae1d83d","analyzedAt":"2026-08-03T19:11:18.437Z","schemaVersion":2}