jackwener/OpenCLI · error · CommandExecutionError
Failed to perform action.
Error message
Failed to perform action.
What it means
selectAndClickAction resolves a conversation, then clicks a chat actions menu item (e.g. rename, archive). If the click helper reports failure, it throws this CommandExecutionError prefixed with the underlying reason (if any) and a hint to verify Codex Desktop is running and the conversation is selectable.
Source
Thrown at clis/codex/_actions.js:221
// action triggers a re-render that could swallow our reply.
const matchedLabel = leadingText(target);
Promise.resolve().then(() => { try { target.click(); } catch {} });
return { ok: true, clicked: matchedLabel };
})()`));
return result || { ok: false, reason: 'Empty result from page.evaluate.' };
}
/**
* Convenience wrapper that selects the target first, then clicks the menu.
*/
export async function selectAndClickAction(page, kwargs, labelOptions) {
const selected = await resolveActionConversation(page, kwargs);
await page.wait(0.4);
const result = await clickChatActionsMenuItem(page, labelOptions);
if (!result.ok) {
const detail = result.detail ? ` ${result.detail}` : '';
throw new CommandExecutionError(
`${result.reason || 'Failed to perform action.'}${detail}`,
'Make sure Codex Desktop is running and the target conversation is selectable.',
);
}
return { ...result, selected };
}
export async function waitForConversationPostcondition(page, ref, predicate, description, timeoutMs = 4000) {
const deadline = Date.now() + timeoutMs;
let lastMatch = null;
while (Date.now() < deadline) {
const projects = await readConversationProjects(page);
lastMatch = findCodexConversation(projects, ref);
if (predicate(lastMatch)) {
return lastMatch;
}
await page.wait(0.2);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Make sure Codex Desktop is running and the conversation is open/selectable, then retry
- Update opencli so its menu-item selectors match the current Codex UI
- Add a small delay/retry around the action so the menu has time to render
- Check result.reason in verbose output to identify the specific click failure
Example fix
// before
await selectAndClickAction(page, kwargs, { label: 'Archive' }); // races menu render
// after
await page.wait(0.5);
await selectAndClickAction(page, kwargs, { label: 'Archive' }); Defensive patterns
Strategy: retry
Validate before calling
await page.waitForSelector('.chat-actions-menu, [role=menu]', { timeout: 5000 });
const selected = await resolveActionConversation(page, kwargs);
if (!selected) throw new Error('No selectable conversation; is Codex Desktop running?'); Type guard
function isClickOk(result) {
return Boolean(result && result.ok === true);
} Try / catch
for (let attempt = 1; attempt <= 3; attempt++) {
try {
await selectAndClickAction(page, kwargs, { label: 'Archive' });
break;
} catch (e) {
if (attempt === 3 || !e.message.includes('Failed to perform action')) throw e;
await page.wait(1);
}
} Prevention
- Ensure Codex Desktop is running and unlocked before automation
- Wait for the actions menu to render before clicking
- Retry transient failures with a short backoff
- Keep opencli selectors in sync with the Codex version you run
When it happens
Trigger: The actions menu item could not be found or clicked: Codex Desktop not running, menu did not open, the item label/selector changed, or the resolved conversation became unselectable between resolution and click.
Common situations: Automation racing the UI (clicking before the menu renders), Codex updated its context-menu structure, the target conversation was closed by the user mid-automation.
Related errors
- Could not switch to ${wantModel} model
- Claude composer is not available on the current page.
- Codex sidebar extraction returned an invalid payload.
- Could not resolve a stable Codex conversation identity.
- ${pickerResult?.reason || 'Failed to open Gemini model picke
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/1566ba50253e20c5.
Report an issue: GitHub.