{"record":{"id":"e46d1f57c95f0152","repo":"can1357/oh-my-pi","slug":"tab-select-requires-a-select-element","errorCode":null,"errorMessage":"tab.select() requires a <select> element","messagePattern":"tab\\.select\\(\\) requires a <select> element","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts","lineNumber":950,"sourceCode":"\t\t\t\t\tinputEvent(element);\n\t\t\t\t\treturn true;\n\t\t\t\tcase \"uncheck\":\n\t\t\t\t\telement.checked = false;\n\t\t\t\t\tinputEvent(element);\n\t\t\t\t\treturn true;\n\t\t\t\tcase \"type\":\n\t\t\t\t\tif (typeof element.focus === \"function\") element.focus();\n\t\t\t\t\tsetValue(element, String(args.text || \"\"), true);\n\t\t\t\t\treturn true;\n\t\t\t\tcase \"fill\":\n\t\t\t\t\tif (typeof element.focus === \"function\") element.focus();\n\t\t\t\t\tsetValue(element, String(args.value || \"\"), false);\n\t\t\t\t\treturn true;\n\t\t\t\tcase \"scrollIntoView\":\n\t\t\t\t\treturn true;\n\t\t\t\tcase \"select\": {\n\t\t\t\t\tconst values = Array.isArray(args.values) ? args.values.map(String) : [String(args.value || \"\")];\n\t\t\t\t\tif (element.tagName !== \"SELECT\") throw new Error(\"tab.select() requires a <select> element\");\n\t\t\t\t\tconst wanted = new Set(values);\n\t\t\t\t\tconst selected = [];\n\t\t\t\t\tfor (const option of Array.from(element.options)) {\n\t\t\t\t\t\toption.selected = wanted.has(option.value);\n\t\t\t\t\t\tif (option.selected) selected.push(option.value);\n\t\t\t\t\t}\n\t\t\t\t\tinputEvent(element);\n\t\t\t\t\treturn selected;\n\t\t\t\t}\n\t\t\t\tcase \"uploadFile\": {\n\t\t\t\t\tif (element.tagName !== \"INPUT\" || element.type !== \"file\") {\n\t\t\t\t\t\tthrow new Error(\"tab.uploadFile() requires an <input type=file> element\");\n\t\t\t\t\t}\n\t\t\t\t\tconst transfer = new DataTransfer();\n\t\t\t\t\tfor (const file of args.files || []) {\n\t\t\t\t\t\tconst bytes = Uint8Array.from(atob(file.data), char => char.charCodeAt(0));\n\t\t\t\t\t\ttransfer.items.add(new File([bytes], file.name, { type: file.type || \"application/octet-stream\" }));\n\t\t\t\t\t}","sourceCodeStart":932,"sourceCodeEnd":968,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/cmux-tab.ts#L932-L968","documentation":"The cmux tab's selector-action bridge (evaluated in the page) implements `select` only for native `<select>` elements. Before iterating `element.options` and setting `option.selected`, it checks `element.tagName !== \"SELECT\"` and throws this Error otherwise. It exists because callers sometimes pass an input, div-based dropdown, or wrong ref, and the browser would otherwise fail cryptically (no `.options`).","triggerScenarios":"Calling the select action with a selector/ref that resolves to a non-<select> element: a custom JS dropdown, an `<input list=...>`, or a stale ref that now points at a wrapper element.","commonSituations":"Automating pages that use component-library dropdowns (React-Select, Material UI) instead of native selects; refs resolved before the DOM hydrated and now stale; copying a working tab.select() call to a page with a different control.","solutions":["Verify the target element with tab.evaluate/getElement that it really is a <select> (check tagName), or re-query with a more specific selector.","For custom (div-based) dropdowns, use click actions to open the dropdown and click the option instead of the select action.","If using `<input list>` comboboxes, set `.value` directly via the setValue path instead of the select action."],"exampleFix":"// before\ntab.select('div.dropdown-menu', ['option-a']);\n// after\nconst tag = await tab.evaluate(`document.querySelector('div.dropdown-menu').tagName`);\nif (tag === 'SELECT') tab.select('div.dropdown-menu', ['option-a']);\nelse { await tab.click('div.dropdown-menu'); await tab.click('text=Option A'); }","handlingStrategy":"validation","validationCode":"const tag = await tab.evaluate(`document.querySelector(${JSON.stringify(sel)})?.tagName`);\nif (tag !== 'SELECT') throw new Error(`select() needs a <select>, got <${tag ?? 'none'}>`);","typeGuard":"function isSelectElement(el): el is HTMLSelectElement { return el instanceof HTMLSelectElement || el?.tagName === 'SELECT'; }","tryCatchPattern":null,"preventionTips":["Check tagName before element-specific actions.","Treat component-library dropdowns as click targets, not native selects.","Re-resolve refs after DOM updates to avoid stale-element mismatches."],"tags":["dom","selector","element-type-mismatch","browser-automation"],"backgroundTag":"wrong-element-type-for-action","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}