jackwener/OpenCLI · error · CommandExecutionError

${before.reason || `Failed to inspect ${name} state.`}${deta

Error message

${before.reason || `Failed to inspect ${name} state.`}${detail}

What it means

defineToggle's pin/unpin flow first reads the conversation's context-menu labels via readConversationMenuLabels; if that inspection fails (before.ok false), this CommandExecutionError is thrown combining before.reason and optional detail. The library cannot even determine the conversation's current pin state, so it aborts rather than clicking blindly.

Source

Thrown at clis/grok/pin.js:40

        description: `${name === 'pin' ? 'Pin' : 'Unpin'} a Grok conversation by ID`,
        domain: GROK_DOMAIN,
        strategy: Strategy.COOKIE,
        browser: true,
        siteSession: 'persistent',
        args: [
            { name: 'id', positional: true, type: 'string', required: true, help: 'Conversation UUID or grok.com/c/<uuid> URL' },
        ],
        columns: ['status', 'id'],
        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,
                );
            }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the conversation id exists — open it in the grok.com tab.
  2. Confirm the browser tab is still logged into grok.com and retry.
  3. Reload the page to rebuild DOM state, then re-run the command.
  4. Update the library if menu selectors changed in a Grok UI update.

Example fix

// before
cli pin --id 00000000-0000-4000-8000-000000000000  // deleted conversation
// after
cli pin --id <id-of-an-existing-conversation>
Defensive patterns

Strategy: validation

Validate before calling

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!UUID_RE.test(id)) throw new Error(`invalid conversation id: ${id}`);
// Also confirm the conversation exists before toggling:
const exists = await page.goto(`https://grok.com/c/${id}`, { waitUntil: 'domcontentloaded' });
if (!exists || page.url().includes('404')) throw new Error(`conversation ${id} not found`);

Type guard

function isGrokConversationId(v) {
  return typeof v === 'string' &&
    /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v.trim());
}

Try / catch

try {
  await cli.pin({ id });
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.startsWith('Failed to inspect')) {
    console.error(`Cannot read pin state for ${id} — verify it exists and the tab is logged in.`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the pin or unpin command with a conversation id whose menu cannot be opened/read — the conversation no longer exists, the menu DOM changed, or the page is in a logged-out state (auth is checked just before).

Common situations: Stale or mistyped conversation id for a deleted chat, Grok UI update renaming menu items, or expired session after the initial isLoggedIn check raced with a logout.

Related errors


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