{"record":{"id":"0782f62ad4452fab","repo":"SeleniumHQ/selenium","slug":"you-may-only-deselect-all-options-of-a-multi-selec","errorCode":null,"errorMessage":"You may only deselect all options of a multi-select","messagePattern":"You may only deselect all options of a multi-select","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"javascript/selenium-webdriver/lib/select.js","lineNumber":351,"sourceCode":"    }\n    return results\n  }\n\n  /**\n   * Returns first Selected Option\n   * @returns {Promise<Element>}\n   */\n  async getFirstSelectedOption() {\n    return (await this.getAllSelectedOptions())[0]\n  }\n\n  /**\n   * Deselects all selected options\n   * @returns {Promise<void>}\n   */\n  async deselectAll() {\n    if (!this.isMultiple()) {\n      throw new Error('You may only deselect all options of a multi-select')\n    }\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())) {","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/selenium-webdriver/lib/select.js#L333-L369","documentation":"INTENDED to be thrown by deselectAll() when the select is not a multi-select, BUT there is a bug: the guard is `if (!this.isMultiple())` where isMultiple() is async and returns a Promise. A Promise is always truthy, so `!Promise` is always false, making this throw effectively UNREACHABLE. Calling deselectAll() on a single-select will NOT raise here; it will proceed and either silently no-op or fail later. Users should not rely on this guard firing.","triggerScenarios":"Calling deselectAll() on a <select> without the 'multiple' attribute. Expectation: this error. Reality (due to the missing await): no error here; subsequent option iteration/click may behave unexpectedly on a single-select.","commonSituations":"Generic helper that calls deselectAll on any select; assuming the library validates multi-ness; migrating from Java/Python Selenium where the guard is correct.","solutions":["Do not depend on this throw — check multi-ness yourself: if (!(await sel.isMultiple())) throw new Error('not multi-select').","Prefer: if (await sel.isMultiple()) { await sel.deselectAll(); } else { handleSingleSelect(); }.","If maintaining the library, fix line 350 to `if (!(await this.isMultiple()))`.","Add your own guard wrapper around Select to make the contract explicit."],"exampleFix":"// before\nawait sel.deselectAll(); // single-select -> no throw (bug), silent surprise\n\n// after\nif (!(await sel.isMultiple())) {\n  throw new Error('deselectAll requires a multi-select');\n}\nawait sel.deselectAll();","handlingStrategy":"validation","validationCode":"async function safeDeselectAll(sel) {\n  if (!(await sel.isMultiple())) {\n    throw new Error('deselectAll requires a multi-select');\n  }\n  await sel.deselectAll();\n}","typeGuard":"async function isMultiSelect(sel) {\n  return Boolean(await sel.isMultiple());\n}","tryCatchPattern":"// NOTE: the library guard is buggy and will NOT throw; you must guard yourself.\nif (!(await sel.isMultiple())) {\n  // handle single-select case (e.g. select a blank option)\n} else {\n  await sel.deselectAll();\n}","preventionTips":["Never rely on this library throw — check isMultiple() yourself with await.","Wrap Select in a helper that enforces the multi-select contract.","If you own the library, fix line 350 to use await."],"tags":["select","deselect","multi-select","async","bug","dead-code"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}