{"id":"8ab4a1c6ad192380","repo":"vitest-dev/vitest","slug":"element-not-found-v-element","errorCode":null,"errorMessage":"Element not found: ${v.element}","messagePattern":"Element not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-playwright/src/commands/select.ts","lineNumber":22,"sourceCode":"import type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const selectOptions: UserEventCommand<UserEvent['selectOptions']> = async (\n  context,\n  selector,\n  userValues,\n  options = {},\n) => {\n  const value = userValues as any as (string | { element: SerializedLocator })[]\n  const selectElement = getDescribedLocator(context, selector)\n\n  const values = await Promise.all(value.map(async (v) => {\n    if (typeof v === 'string') {\n      return v\n    }\n    const elementHandler = await getDescribedLocator(context, v.element).elementHandle()\n    if (!elementHandler) {\n      throw new Error(`Element not found: ${v.element}`)\n    }\n    return elementHandler\n  })) as (readonly string[]) | (readonly ElementHandle[])\n\n  await selectElement.selectOption(values, options)\n}\n","sourceCodeStart":4,"sourceCodeEnd":29,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser-playwright/src/commands/select.ts#L4-L29","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for the option to be attached before selecting: await page.element(locator).waitFor().","Verify the <option> exists with an expect(locator).toBeVisible() assertion first.","Prefer passing option values as plain strings (the value attribute) instead of element locators, which avoids the handle lookup.","Re-query the locator immediately before the select to avoid staleness."],"exampleFix":"// before\nawait page.selectOptions(selectEl, [{ element: optionLocator }]) // option not in DOM\n\n// after\nawait page.element(optionLocator).waitFor({ state: 'attached' })\nawait page.selectOptions(selectEl, [{ element: optionLocator }])\n// or simpler: pass value strings\nawait page.selectOptions(selectEl, ['option-value-1'])","handlingStrategy":"validation","validationCode":"const handle = await page.element(locator).elementHandle()\nif (!handle) throw new Error('option not attached; cannot select')\nawait page.selectOptions(selectEl, [{ element: locator }])","typeGuard":"async function optionAttached(locator: SerializedLocator): Promise<boolean> {\n  const h = await page.element(locator).elementHandle()\n  return h !== null\n}","tryCatchPattern":"try {\n  await page.selectOptions(selectEl, [{ element: loc }])\n} catch (err) {\n  if (err instanceof Error && /Element not found/.test(err.message)) {\n    await page.element(loc).waitFor({ state: 'attached' })\n    await page.selectOptions(selectEl, [{ element: loc }])\n  } else throw err\n}","preventionTips":["Wait for the <option> to be attached before selecting.","Prefer value-string options over element locators to avoid handle lookups.","Re-query locators immediately before use to avoid staleness after re-renders."],"tags":["browser","playwright","selectoptions","user-event","dom","vitest"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}