{"record":{"id":"046aa0768b894f7e","repo":"SeleniumHQ/selenium","slug":"you-may-only-deselect-options-of-a-multi-select","errorCode":null,"errorMessage":"You may only deselect options of a multi-select","messagePattern":"You may only deselect options of a multi-select","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"javascript/selenium-webdriver/lib/select.js","lineNumber":370,"sourceCode":"    }\n\n    const options = await this.getOptions()\n\n    for (let option of options) {\n      if (await option.isSelected()) {\n        await option.click()\n      }\n    }\n  }\n\n  /**\n   *\n   * @param {string|Number}text text of option to deselect\n   * @returns {Promise<void>}\n   */\n  async deselectByVisibleText(text) {\n    if (!(await this.isMultiple())) {\n      throw new Error('You may only deselect options of a multi-select')\n    }\n\n    /**\n     * convert value into string\n     */\n    text = typeof text === 'number' ? text.toString() : text\n\n    const optionElement = await this.element.findElement(\n      By.xpath('.//option[normalize-space(.) = ' + escapeQuotes(text) + ']'),\n    )\n    if (await optionElement.isSelected()) {\n      await optionElement.click()\n    }\n  }\n\n  /**\n   *\n   * @param {Number} index       index of option element to deselect","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/selenium-webdriver/lib/select.js#L352-L388","documentation":"Thrown by deselectByVisibleText() when the select is not a multi-select. Unlike deselectAll (error 91), this guard correctly uses `await this.isMultiple()`, so it fires reliably. The method also expects the text to match an option (it uses findElement which throws NoSuchElementError if absent). Generic Error for the multi-select check.","triggerScenarios":"Calling deselectByVisibleText on a <select> without the multiple attribute. A single-select cannot have a 'deselected' state in the multi-select sense, so the operation is rejected up front.","commonSituations":"Generic form helpers; test code reused across single and multi selects; assuming a dropdown is multi because it visually allows clearing.","solutions":["Guard before calling: if (await sel.isMultiple()) await sel.deselectByVisibleText(t).","Confirm the <select> has the multiple attribute in the page.","Wrap in try/catch and treat this as a no-op for single selects if appropriate.","Use a Select helper that branches on isMultiple()."],"exampleFix":"// before\nawait sel.deselectByVisibleText('X'); // single-select -> throws\n\n// after\nif (await sel.isMultiple()) {\n  await sel.deselectByVisibleText('X');\n} else {\n  // single-select: deselect by picking a different/blank option\n}","handlingStrategy":"validation","validationCode":"async function safeDeselectByText(sel, text) {\n  if (!(await sel.isMultiple())) throw new Error('requires multi-select');\n  await sel.deselectByVisibleText(text);\n}","typeGuard":"async function isMultiSelect(sel) {\n  return Boolean(await sel.isMultiple());\n}","tryCatchPattern":"try {\n  await sel.deselectByVisibleText(t);\n} catch (e) {\n  if (/multi-select/.test(e.message)) { /* no-op for single selects */ }\n  else throw e;\n}","preventionTips":["Branch all deselect* calls on await sel.isMultiple().","Confirm the multiple attribute on the element for dropdowns you expect to be multi.","Centralize deselect logic in a Select helper."],"tags":["select","deselect","multi-select","validation"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}