{"record":{"id":"befb1f9ce6cbd95f","repo":"jackwener/OpenCLI","slug":"codex-picker-selection-did-not-reach-the-composer","errorCode":null,"errorMessage":"Codex picker selection did not reach the composer.","messagePattern":"Codex picker selection did not reach the composer\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/codex/send.js","lineNumber":203,"sourceCode":"    })()`));\n            if (clicked !== true) {\n                throw new CommandExecutionError('Codex picker option disappeared before it could be clicked.', `wanted=${picked.title}`);\n            }\n            // The click above is deferred, so verify it landed: the picker must\n            // close and the composer must hold a chip for the picked option.\n            let applied = null;\n            for (let attempt = 0; attempt < 20; attempt += 1) {\n                const state = await readComposerState(page);\n                const pickerOpen = unwrapEvaluateResult(await page.evaluate(`Array.from(document.querySelectorAll('${PICKER_ITEM_SELECTOR}')).some((it) => it instanceof HTMLElement && !!it.offsetParent)`)) === true;\n                if (!pickerOpen && state.chips.some((chip) => chipMatchesLabel(chip, picked.title))) {\n                    applied = state;\n                    break;\n                }\n                applied = state;\n                await page.wait(0.1);\n            }\n            if (!applied || !applied.chips.some((chip) => chipMatchesLabel(chip, picked.title))) {\n                throw new CommandExecutionError(\n                    'Codex picker selection did not reach the composer.',\n                    `expected=${picked.title} ${describeComposerState(applied ?? { text: '', chips: [] })}`,\n                );\n            }\n        }\n        await page.pressKey('Enter');\n        let state = await pollComposerState(page);\n        if (state.text) {\n            // The picker consumes Enter to insert the highlighted entry, so a\n            // still-loaded composer is either the untouched draft or the chip\n            // the picker resolved. Anything else was rewritten: never submit.\n            const slashToken = /^\\/\\S+$/.test(textToInsert) ? textToInsert.slice(1) : '';\n            const chipLabel = picked ? picked.title : slashToken;\n            const unchangedDraft = state.chips.length === 0 && state.text === String(textToInsert).trim();\n            const pickerResolvedCommand = chipLabel !== ''\n                && state.chips.length === 1\n                && state.nonChipText === ''\n                && chipMatchesLabel(state.chips[0], chipLabel);","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/codex/send.js#L185-L221","documentation":"After the picker option click succeeds, the library polls `readComposerState` up to 20 times to confirm the composer now holds a chip matching the picked option. If no state shows a matching chip (`applied` is null or `chipMatchesLabel` fails), the selection silently failed and this error is thrown, preventing a send of the wrong content.","triggerScenarios":"Clicking a picker option did not insert its chip into the composer within the polling window — the click landed on a non-interactive overlay, the chip label differs from `picked.title`, or the picker was closed without applying the selection.","commonSituations":"Codex UI version changed so chips render differently or labels are truncated differently; click hit an overlay instead of the option; picker selection applied to a different composer than the one being polled.","solutions":["Re-run the send; transient click/apply races usually resolve on retry.","Check that the `--pick <label>` text matches the picker option label exactly (case/spacing).","Press Escape in Codex to clear any half-applied state, then retry.","If it persists after a Codex update, the chip rendering changed — update or patch `chipMatchesLabel`."],"exampleFix":"// before\nawait runCodexSend({ pick: 'Plan Review' }); // label mismatch\n// after\nawait runCodexSend({ pick: 'Plan review' }); // exact picker label","handlingStrategy":"validation","validationCode":"// Ensure the pick label matches an existing picker option before sending\nconst labels = await readPickerOptionLabels(page);\nif (!labels.includes(pickLabel)) throw new Error(`Pick label '${pickLabel}' not in options: ${labels.join(', ')}`);","typeGuard":"const isAppliedState = (s) => s != null && Array.isArray(s.chips) && s.chips.some((c) => chipMatchesLabel(c, expectedTitle));","tryCatchPattern":"try {\n  await codexSend({ pick: label });\n} catch (e) {\n  if (String(e.message).includes('did not reach the composer')) {\n    await page.pressKey('Escape'); // reset composer\n    // verify label then retry once\n  } else throw e;\n}","preventionTips":["Use the exact picker option label (case, spacing, punctuation).","Press Escape to clear any half-applied picker state before retrying.","Avoid running sends while the Codex page is re-rendering.","After a Codex update, verify chip labels still match via composer state."],"tags":["codex","picker","composer","chip","automation"],"backgroundTag":"ui-action-not-applied","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}