jackwener/OpenCLI · error · CommandExecutionError
${result?.reason || `Failed to ${name} conversation.`}${deta
Error message
${result?.reason || `Failed to ${name} conversation.`}${detail} What it means
After reading the menu, defineToggle clicks the pin/unpin menu item via clickConversationMenuItem; if the click result is missing or reports ok:false, this CommandExecutionError is thrown with result.reason (or a 'Failed to pin/unpin conversation' default) plus detail. It means the menu item itself could not be clicked or the click action failed.
Source
Thrown at clis/grok/pin.js:49
func: async (page, kwargs) => {
const id = parseGrokSessionId(kwargs.id);
await ensureOnGrok(page);
if (!(await isLoggedIn(page))) throw authRequired();
const expectedState = name === 'pin' ? 'pinned' : 'unpinned';
const before = await readConversationMenuLabels(page, id);
if (!before.ok) {
const detail = before.detail ? ` ${before.detail}` : '';
throw new CommandExecutionError(`${before.reason || `Failed to inspect ${name} state.`}${detail}`, SESSION_HINT);
}
if (getPinStateFromMenuLabels(before.labels) === expectedState) {
return [{ status: `already-${expectedState}`, id }];
}
const result = await clickConversationMenuItem(page, id, accessLabels);
if (!result || !result.ok) {
const detail = result?.detail ? ` ${result.detail}` : '';
throw new CommandExecutionError(`${result?.reason || `Failed to ${name} conversation.`}${detail}`, SESSION_HINT);
}
const verified = await waitForConversationPinState(page, id, expectedState);
if (!verified.ok) {
const labels = verified.labels?.length ? ` labels=${JSON.stringify(verified.labels)}` : '';
throw new CommandExecutionError(
`${name} menu item was clicked, but the conversation did not verify as ${expectedState}.${labels}`,
SESSION_HINT,
);
}
return [{ status: name === 'pin' ? 'pinned' : 'unpinned', id }];
},
});
}
// Grok's context menu shows EITHER "置顶" OR "取消置顶" depending on the
// current pin state, never both. We register two commands that bind to
// the matching label so callers can use whichever they want.
defineToggle('pin', ['置顶', 'pin']);View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command — transient overlay/animation races usually succeed on retry.
- Check the reason/detail in the message for the failing click step.
- Reload the grok.com tab and ensure no dialogs are open, then retry.
- Update the library if Grok's menu markup changed.
Example fix
// before cli unpin --id <id> // menu closed before click // after // keep the tab focused and retry: cli unpin --id <id>
Defensive patterns
Strategy: retry
Validate before calling
// Ensure no overlay blocks clicks before toggling:
const overlay = await page.$('.modal, [role=dialog]');
if (overlay) throw new Error('close open dialogs before pin/unpin operations'); Try / catch
async function pinWithRetry(id, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { return await cli.pin({ id }); }
catch (e) {
if (e instanceof CommandExecutionError && /Failed to pin conversation/.test(e.message) && i < attempts - 1) {
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
continue;
}
throw e;
}
}
} Prevention
- Retry menu clicks — animation and re-render races are transient.
- Keep the tab focused so hover menus open reliably.
- Dismiss toasts/dialogs that can intercept clicks.
- Update the library after Grok UI changes.
When it happens
Trigger: clickConversationMenuItem returns {ok:false} or null because the menu closed mid-click, the item selector missed, the element was intercepted by an overlay, or the item is disabled.
Common situations: Animated menus that close before the click lands, Grok UI rename of the 'Pin'/'Unpin' items, an interfering notification toast, or the conversation list re-rendering during the click.
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.
- Failed to perform action.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7e5452dcac732c22.
Report an issue: GitHub.