SeleniumHQ/selenium · error · Error

You may only deselect all options of a multi-select

Error message

You may only deselect all options of a multi-select

What it means

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.

Source

Thrown at javascript/selenium-webdriver/lib/select.js:351

    }
    return results
  }

  /**
   * Returns first Selected Option
   * @returns {Promise<Element>}
   */
  async getFirstSelectedOption() {
    return (await this.getAllSelectedOptions())[0]
  }

  /**
   * Deselects all selected options
   * @returns {Promise<void>}
   */
  async deselectAll() {
    if (!this.isMultiple()) {
      throw new Error('You may only deselect all options of a multi-select')
    }

    const options = await this.getOptions()

    for (let option of options) {
      if (await option.isSelected()) {
        await option.click()
      }
    }
  }

  /**
   *
   * @param {string|Number}text text of option to deselect
   * @returns {Promise<void>}
   */
  async deselectByVisibleText(text) {
    if (!(await this.isMultiple())) {

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Do not depend on this throw — check multi-ness yourself: if (!(await sel.isMultiple())) throw new Error('not multi-select').
  2. Prefer: if (await sel.isMultiple()) { await sel.deselectAll(); } else { handleSingleSelect(); }.
  3. If maintaining the library, fix line 350 to `if (!(await this.isMultiple()))`.
  4. Add your own guard wrapper around Select to make the contract explicit.

Example fix

// before
await sel.deselectAll(); // single-select -> no throw (bug), silent surprise

// after
if (!(await sel.isMultiple())) {
  throw new Error('deselectAll requires a multi-select');
}
await sel.deselectAll();
Defensive patterns

Strategy: validation

Validate before calling

async function safeDeselectAll(sel) {
  if (!(await sel.isMultiple())) {
    throw new Error('deselectAll requires a multi-select');
  }
  await sel.deselectAll();
}

Type guard

async function isMultiSelect(sel) {
  return Boolean(await sel.isMultiple());
}

Try / catch

// NOTE: the library guard is buggy and will NOT throw; you must guard yourself.
if (!(await sel.isMultiple())) {
  // handle single-select case (e.g. select a blank option)
} else {
  await sel.deselectAll();
}

Prevention

When it happens

Trigger: 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.

Common situations: Generic helper that calls deselectAll on any select; assuming the library validates multi-ness; migrating from Java/Python Selenium where the guard is correct.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/0782f62ad4452fab. Report an issue: GitHub.