vitest-dev/vitest · error · Error

Element not found: ${v.element}

Error message

Element not found: ${v.element}

What it means

Thrown by the Playwright selectOptions user-event command when one of the provided values is a SerializedLocator whose underlying DOM element cannot be resolved to an ElementHandle (elementHandle() returned null). This means the selector matched nothing in the iframe at select time.

Source

Thrown at packages/browser-playwright/src/commands/select.ts:22

import type { UserEventCommand } from './utils'
import { getDescribedLocator } from './utils'

export const selectOptions: UserEventCommand<UserEvent['selectOptions']> = async (
  context,
  selector,
  userValues,
  options = {},
) => {
  const value = userValues as any as (string | { element: SerializedLocator })[]
  const selectElement = getDescribedLocator(context, selector)

  const values = await Promise.all(value.map(async (v) => {
    if (typeof v === 'string') {
      return v
    }
    const elementHandler = await getDescribedLocator(context, v.element).elementHandle()
    if (!elementHandler) {
      throw new Error(`Element not found: ${v.element}`)
    }
    return elementHandler
  })) as (readonly string[]) | (readonly ElementHandle[])

  await selectElement.selectOption(values, options)
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Wait for the option to be attached before selecting: await page.element(locator).waitFor().
  2. Verify the <option> exists with an expect(locator).toBeVisible() assertion first.
  3. Prefer passing option values as plain strings (the value attribute) instead of element locators, which avoids the handle lookup.
  4. Re-query the locator immediately before the select to avoid staleness.

Example fix

// before
await page.selectOptions(selectEl, [{ element: optionLocator }]) // option not in DOM

// after
await page.element(optionLocator).waitFor({ state: 'attached' })
await page.selectOptions(selectEl, [{ element: optionLocator }])
// or simpler: pass value strings
await page.selectOptions(selectEl, ['option-value-1'])
Defensive patterns

Strategy: validation

Validate before calling

const handle = await page.element(locator).elementHandle()
if (!handle) throw new Error('option not attached; cannot select')
await page.selectOptions(selectEl, [{ element: locator }])

Type guard

async function optionAttached(locator: SerializedLocator): Promise<boolean> {
  const h = await page.element(locator).elementHandle()
  return h !== null
}

Try / catch

try {
  await page.selectOptions(selectEl, [{ element: loc }])
} catch (err) {
  if (err instanceof Error && /Element not found/.test(err.message)) {
    await page.element(loc).waitFor({ state: 'attached' })
    await page.selectOptions(selectEl, [{ element: loc }])
  } else throw err
}

Prevention

When it happens

Trigger: Calling page.selectOptions(select, [{ element: locator }]) where locator points to an <option> that is not present, not yet rendered, or lives in a different frame. Also when passing a stale locator captured before a re-render.

Common situations: Selecting options in async-loaded dropdowns, shadow-DOM selects, selects re-rendered after a state change, or racing the select before the list is populated.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/8ab4a1c6ad192380.json. Report an issue: GitHub.