{"record":{"id":"89faec01fd0fd975","repo":"puppeteer/puppeteer","slug":"element-is-not-a-select-element","errorCode":null,"errorMessage":"Element is not a <select> element.","messagePattern":"Element is not a <select> element\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/puppeteer-core/src/api/ElementHandle.ts","lineNumber":985,"sourceCode":"   */\n  @throwIfDisposed()\n  @bindIsolatedHandle\n  async select(...values: string[]): Promise<string[]> {\n    for (const value of values) {\n      assert(\n        isString(value),\n        'Values must be strings. Found value \"' +\n          value +\n          '\" of type \"' +\n          typeof value +\n          '\"',\n      );\n    }\n\n    return await this.evaluate((element, vals): string[] => {\n      const values = new Set(vals);\n      if (!(element instanceof HTMLSelectElement)) {\n        throw new Error('Element is not a <select> element.');\n      }\n\n      const selectedValues = new Set<string>();\n      if (!element.multiple) {\n        for (const option of element.options) {\n          option.selected = false;\n        }\n        for (const option of element.options) {\n          if (values.has(option.value)) {\n            option.selected = true;\n            selectedValues.add(option.value);\n            break;\n          }\n        }\n      } else {\n        for (const option of element.options) {\n          option.selected = values.has(option.value);\n          if (option.selected) {","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/puppeteer/puppeteer/blob/d484e21c17f6023826fefdcdeeb553e04a7aaed8/packages/puppeteer-core/src/api/ElementHandle.ts#L967-L1003","documentation":"Thrown by ElementHandle.select() when the resolved DOM node is not an HTMLSelectElement. The check runs inside the page via evaluate(), so the element's runtime type matters, not the TypeScript generic. Puppeteer requires a real <select> because it iterates element.options and mutates option.selected.","triggerScenarios":"Calling handle.select('blue') on an ElementHandle that resolves to an <input>, <div>, or any non-<select> node. Common when a selector matches a wrapper <div> around a custom dropdown, or when the page swapped the <select> for a custom component between querySelector and select().","commonSituations":"Selecting from a custom dropdown widget that uses <ul>/<li> or <div> instead of a native <select>; matching a <label> or container element rather than the <select> itself; the element was re-rendered after the handle was acquired.","solutions":["Verify the handle points to the <select> element: await page.$eval('select#state', el => el.tagName) before calling select().","If the dropdown is custom (non-native <select>), use click() on the trigger and then click() on the desired option instead of select().","Narrow the selector to target the <select> directly, e.g. 'select#country' rather than a parent wrapper.","Re-query the handle right before selecting if the page re-renders frequently."],"exampleFix":"// before\nconst handle = await page.$('.dropdown');\nawait handle.select('blue');\n\n// after\nconst handle = await page.$('select.dropdown');\nawait handle.select('blue');","handlingStrategy":"type-guard","validationCode":"// Before calling select(), confirm the element is a <select>\nconst isSelect = await handle.evaluate(el => el instanceof HTMLSelectElement);\nif (!isSelect) {\n  throw new Error('Refusing to call select() on a non-<select> element');\n}\nawait handle.select('blue');","typeGuard":"async function isSelectElement(handle: import('puppeteer').ElementHandle): Promise<boolean> {\n  return handle.evaluate(el => el instanceof HTMLSelectElement);\n}","tryCatchPattern":"try {\n  await handle.select('blue');\n} catch (e) {\n  if (e.message.includes('not a <select>')) {\n    // fall back to clicking option elements in a custom dropdown\n  } else throw e;\n}","preventionTips":["Use a selector that targets the <select> tag directly, not a wrapper.","Assert element.tagName === 'SELECT' in a helper before select().","Re-query the handle right before select() if the page re-renders.","For custom dropdowns, click the trigger and options instead of select()."],"tags":["dom","element-handle","select","validation"],"backgroundTag":null,"analyzedSha":"d484e21c17f6023826fefdcdeeb553e04a7aaed8","analyzedAt":"2026-08-12T06:33:19.665Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}