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

  1. Make sure Codex Desktop is running and the conversation is open/selectable, then retry
  2. Update opencli so its menu-item selectors match the current Codex UI
  3. Add a small delay/retry around the action so the menu has time to render
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/1566ba50253e20c5. Report an issue: GitHub.