jackwener/OpenCLI · error · CommandExecutionError

${send?.reason || 'Failed to send Grok prompt'}

Error message

${send?.reason || 'Failed to send Grok prompt'}

What it means

After sendPrompt runs, the command checks its result; on failure it first re-verifies login (throwing AuthRequiredError if logged out) and otherwise throws CommandExecutionError carrying send.reason or the default 'Failed to send Grok prompt'. This means the composer was present and the session valid, but submission still failed for another reason.

Source

Thrown at clis/grok/send.js:46

    func: async (page, kwargs) => {
        const prompt = String(kwargs.prompt || '').trim();
        if (!prompt) throw new ArgumentError('prompt', 'is required');
        const startFresh = normalizeBooleanFlag(kwargs.new, false);

        await ensureOnGrok(page);
        if (startFresh) {
            await startNewChat(page);
        }

        const send = await sendMessage(page, prompt);
        if (!send?.ok) {
            // If the composer is missing, the most likely cause is that the
            // signed-in session expired (Grok then renders a sign-in CTA in
            // place of the composer). Surface that as AuthRequiredError so
            // agents can prompt for re-auth instead of treating it as a
            // generic execution failure.
            if (!(await isLoggedIn(page))) throw authRequired();
            throw new CommandExecutionError(send?.reason || 'Failed to send Grok prompt');
        }
        return [{ Status: 'sent', Prompt: prompt }];
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read send.reason in the message for the specific failing step.
  2. Retry after a short wait — rate limits and transient click failures often clear.
  3. Reload the tab, dismiss any dialogs, confirm the composer accepts manual input.
  4. Check for Grok usage limits on the account; update the library if the UI changed.

Example fix

// before
cli send 'hello'  // {ok:false, reason:'send click did not submit'}
// after
// dismiss the quota dialog in the tab / wait out the rate limit, then
cli send 'hello'
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm session and composer before sending:
const composer = await page.waitForSelector('textarea', { timeout: 5000 }).catch(() => null);
if (!composer) throw new Error('composer missing — session may need re-auth');

Try / catch

try {
  await cli.send({ prompt });
} catch (e) {
  if (e instanceof AuthRequiredError) {
    console.error('Re-authenticate grok.com in the automated tab.');
  } else if (e instanceof CommandExecutionError && /Failed to send Grok prompt/.test(e.message)) {
    console.warn('Send failed while logged in; retrying after backoff...');
    await new Promise(r => setTimeout(r, 5000));
    return cli.send({ prompt });
  } else throw e;
}

Prevention

When it happens

Trigger: sendPrompt returns {ok:false} with a reason while isLoggedIn(page) is true — e.g. the send click didn't register, the composer rejected input, or submission was blocked by a rate limit/dialog.

Common situations: Grok rate limiting prompts, an unexpected modal (quota upsell, safety notice) intercepting submission, partial session validity, or DOM changes breaking send mechanics without logging the user out.

Related errors


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