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

  1. Re-run the command — transient overlay/animation races usually succeed on retry.
  2. Check the reason/detail in the message for the failing click step.
  3. Reload the grok.com tab and ensure no dialogs are open, then retry.
  4. 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

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


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