{"record":{"id":"e07d85184d8edf27","repo":"jackwener/OpenCLI","slug":"codex-picker-did-not-open-after-typing-the-command","errorCode":null,"errorMessage":"Codex picker did not open after typing the command.","messagePattern":"Codex picker did not open after typing the command\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/codex/send.js","lineNumber":156,"sourceCode":"      const wait = (ms) => new Promise((r) => setTimeout(r, ms));\n      let items = [];\n      for (let attempt = 0; attempt < 20; attempt += 1) {\n        items = Array.from(document.querySelectorAll('${PICKER_ITEM_SELECTOR}'))\n          .filter((it) => it instanceof HTMLElement && it.offsetParent);\n        if (items.length) break;\n        await wait(75);\n      }\n      // Picker titles are split into per-character spans for match\n      // highlighting, so read the leading truncate div for the title and the\n      // concatenated textContent (title plus description) for substrings.\n      return items.map((el) => {\n        const text = (el.textContent || '').replace(/\\\\s+/g, ' ').trim();\n        const lead = el.querySelector('[class*=\"truncate\"]');\n        return { title: lead ? (lead.textContent || '').replace(/\\\\s+/g, ' ').trim() : text, text };\n      });\n    })()`));\n            if (!Array.isArray(options) || options.length === 0) {\n                throw new CommandExecutionError('Codex picker did not open after typing the command.', 'Check that the text opens a picker, or drop --pick.');\n            }\n            picked = findUniquePickerOption(options, pick);\n            if (!picked) {\n                throw new CommandExecutionError('No picker option matched.', `wanted=${pick} available=${JSON.stringify(options.map((option) => option.title))}`);\n            }\n            const clicked = unwrapEvaluateResult(await page.evaluate(`(() => {\n      const items = Array.from(document.querySelectorAll('${PICKER_ITEM_SELECTOR}'))\n        .filter((it) => it instanceof HTMLElement && it.offsetParent);\n      const target = items[${picked.index}];\n      if (!target) return false;\n      const rect = target.getBoundingClientRect();\n      const init = {\n        bubbles: true, cancelable: true, button: 0, buttons: 1,\n        clientX: Math.round(rect.left + rect.width / 2),\n        clientY: Math.round(rect.top + rect.height / 2),\n      };\n      // The picker only responds to the full pointer chain, and deferring it\n      // keeps the eval response ahead of the re-render that closes the picker.","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/codex/send.js#L138-L174","documentation":"After typing the composer text, the library expects typing to open the Codex picker (a list of [data-list-navigation-item] elements). If the script finds no visible picker options, it throws CommandExecutionError because --pick cannot proceed without a picker.","triggerScenarios":"Using --pick with composer text that does not trigger any picker in the current Codex UI, or the picker failed to render/open before the options-collection script ran.","commonSituations":"Passing plain text that opens no picker (only specific prefixes like '/' or '@' open menus); Codex UI change renaming the data-list-navigation-item attribute; very slow page where the picker hadn't rendered yet; picker closed by an early Enter/blur.","solutions":["Drop --pick if your text doesn't open a picker (the error detail explicitly suggests this).","Use text that actually triggers the picker, e.g. a leading '/' command, and verify manually in the browser.","Check whether a Codex UI update changed the picker markup and update the CLI accordingly.","Retry — if the page was slow, the picker may simply not have rendered in time."],"exampleFix":"// before\n$ codex send --pick \"plan\" \"hello\"\n// CommandExecutionError: Codex picker did not open after typing the command.\n\n// after\n$ codex send --pick \"Plan mode\" \"/plan hello\"   # text that opens a picker\n# or drop --pick:\n$ codex send \"hello\"","handlingStrategy":"fallback","validationCode":"// Only pass --pick when the composer text actually triggers a picker\nconst opensPicker = /^(\\/|@|#)/.test(text);\nif (pick && !opensPicker) console.warn('--pick ignored: text does not open a picker');","typeGuard":null,"tryCatchPattern":"try {\n  await codexSend({ text, pick });\n} catch (e) {\n  if (e instanceof CommandExecutionError && /picker did not open/.test(e.message)) {\n    return codexSend({ text: textWithoutPickerPrefix }); // retry without --pick\n  }\n  throw e;\n}","preventionTips":["Only use --pick with composer text known to open a picker (e.g. '/' commands).","Verify picker behavior manually in the browser after Codex UI updates.","Add a small wait/retry for slow pages before collecting picker options."],"tags":["picker","ui-automation","codex","dom-automation"],"backgroundTag":"picker-not-open","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}