{"record":{"id":"67be6815e36812d0","repo":"jackwener/OpenCLI","slug":"gmail-operation-requires-native-browser-keyboar","errorCode":null,"errorMessage":"Gmail ${operation} requires native browser keyboard input","messagePattern":"Gmail (.+?) requires native browser keyboard input","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gmail/utils.js","lineNumber":475,"sourceCode":"    field.focus();\n    field.select();\n    return true;\n  }`), `${operation} search preparation`);\n  if (prepared !== true) throw new CommandExecutionError(`Gmail ${operation} could not find the search input`);\n  if (typeof page.nativeType !== 'function') {\n    throw new CommandExecutionError(`Gmail ${operation} requires native browser input`);\n  }\n  await page.nativeType(query);\n  const actual = unwrapBrowserResult(await page.evaluate(`() => document.querySelector('input[name=\"q\"]')?.value || ''`), `${operation} search input verification`);\n  if (actual !== query) throw new CommandExecutionError(`Gmail ${operation} could not set the search query exactly`);\n  if (typeof page.cdp === 'function') {\n    const key = { key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13, nativeVirtualKeyCode: 13 };\n    await page.cdp('Input.dispatchKeyEvent', { type: 'rawKeyDown', ...key });\n    await page.cdp('Input.dispatchKeyEvent', { type: 'keyUp', ...key });\n  } else if (typeof page.nativeKeyPress === 'function') {\n    await page.nativeKeyPress('Enter');\n  } else {\n    throw new CommandExecutionError(`Gmail ${operation} requires native browser keyboard input`);\n  }\n}\n\nexport async function queryThreads(page, query, { account = 0, limit = DEFAULT_LIMIT } = {}) {\n  const normalizedQuery = cleanString(query);\n  if (!normalizedQuery) throw new ArgumentError('Gmail search query cannot be empty');\n  await ensureGmailReady(page, account, 'thread list');\n  await installGmailCapture(page, account, 'bv', 'thread list');\n\n  const rows = [];\n  const seen = new Set();\n  const pages = Math.ceil(limit / PAGE_SIZE);\n  for (let pageNumber = 1; pageNumber <= pages; pageNumber += 1) {\n    if (pageNumber === 1) {\n      await submitSearch(page, normalizedQuery, 'thread list');\n    } else {\n      const target = unwrapBrowserResult(await page.evaluate(`() => {\n        const labels = /(older|较旧|較舊|下一页|下一頁)/i;","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gmail/utils.js#L457-L493","documentation":"After typing, submitSearch must press Enter natively; if the page exposes neither cdp (for Input.dispatchKeyEvent) nor nativeKeyPress, it throws this CommandExecutionError. A synthetic DOM Enter event would not reliably trigger Gmail's search, so the library requires a real keyboard path and fails otherwise.","triggerScenarios":"queryThreads/listLabels reaches the Enter step with a page wrapper that has neither page.cdp nor page.nativeKeyPress — e.g. a minimal shim or a driver bridge missing keyboard dispatch.","commonSituations":"Custom page objects with evaluate/sleep but no keyboard/CDP passthrough; restricted environments where CDP is disabled; version mismatch where the driver exposes different key-dispatch names.","solutions":["Use the library's standard page wrapper that provides cdp or nativeKeyPress","Implement nativeKeyPress on your wrapper via the driver's keyboard API (e.g. page.keyboard.press('Enter'))","Expose a CDP passthrough (page.cdp delegating to CDPSession.send) if using Puppeteer directly","Check typeof page.cdp === 'function' || typeof page.nativeKeyPress === 'function' before running Gmail searches"],"exampleFix":"// before: wrapper lacks both dispatch paths\nawait queryThreads(page, 'in:unread');\n// after: add a native key press to the wrapper\npage.nativeKeyPress = (key) => page.keyboard.press(key);\nawait queryThreads(page, 'in:unread');","handlingStrategy":"validation","validationCode":"if (typeof page?.cdp !== 'function' && typeof page?.nativeKeyPress !== 'function') {\n  throw new Error('page wrapper must support cdp() or nativeKeyPress() for Gmail search');\n}","typeGuard":"function supportsEnterKey(page) {\n  return typeof page?.cdp === 'function' || typeof page?.nativeKeyPress === 'function';\n}","tryCatchPattern":"try {\n  await queryThreads(page, 'has:attachment');\n} catch (e) {\n  if (/requires native browser keyboard input/.test(e.message)) {\n    console.error('Add nativeKeyPress or cdp passthrough to the page wrapper');\n  } else throw e;\n}","preventionTips":["Provide cdp() or nativeKeyPress() on any custom page wrapper","Use the library's standard wrapper in restricted environments where CDP is disabled","Run a startup capability check for keyboard dispatch before Gmail operations"],"tags":["browser-automation","api-mismatch","gmail","keyboard"],"backgroundTag":"missing-api-method","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}