{"record":{"id":"076380b4f4c7a4df","repo":"jackwener/OpenCLI","slug":"reason-detail","errorCode":null,"errorMessage":"${reason}${detail}","messagePattern":"\\$\\{reason\\}\\$\\{detail\\}","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/grok/ask.js","lineNumber":59,"sourceCode":"        const timeoutSeconds = kwargs.timeout || 120;\n        const newChat = normalizeBooleanFlag(kwargs.new);\n\n        if (newChat) {\n            await startNewChat(page);\n        } else {\n            await ensureOnGrok(page);\n        }\n\n        if (!(await isLoggedIn(page))) {\n            throw authRequired();\n        }\n\n        const baselineLastAssistantId = await getBaselineLastAssistantId(page);\n        const sendResult = await sendMessage(page, prompt);\n        if (!sendResult || !sendResult.ok) {\n            const reason = sendResult?.reason || 'Unable to send the prompt to Grok.';\n            const detail = sendResult?.detail ? ` ${sendResult.detail}` : '';\n            throw new CommandExecutionError(`${reason}${detail}`, SESSION_HINT);\n        }\n\n        const result = await waitForAnswer(page, prompt, timeoutSeconds, baselineLastAssistantId);\n        if (result.status === 'ok') {\n            return [{ response: result.assistant.text }];\n        }\n        // Partial: streaming was seen but did not stabilize; keep the best-effort\n        // text rather than throwing — the caller asked us to wait, not to discard.\n        if (result.status === 'partial' && result.assistant) {\n            return [{ response: result.assistant.text }];\n        }\n        throw new TimeoutError('grok ask response', timeoutSeconds);\n    },\n});\n\nexport const __test__ = {\n    getBaselineLastAssistantId,\n};","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/grok/ask.js#L41-L77","documentation":"The grok ask command throws a CommandExecutionError when sendMessage() fails to submit the prompt into the Grok chat UI — the function returned null/undefined or {ok:false}. The message is the sender's reason plus optional detail, and the SESSION_HINT ('Likely login/auth/challenge/session issue') is attached because a failed send almost always means the persistent browser session is logged out, blocked, or showing a challenge instead of the composer. This is thrown before any waiting for a response, so it reflects message-submission failure, not response timeout.","triggerScenarios":"Running `grok ask \"...\"` when: (1) isLoggedIn(page) passed but the composer element disappeared before/while typing; (2) the send button or Enter-key submission failed because the page rendered a Cloudflare/X challenge or an upgrade/paywall modal; (3) the send button is disabled (Grok is mid-response from a previous turn, or a usage/rate limit banner blocks sending); (4) sendMessage returned null because a DOM selector for the textarea/composer changed or the chat area never loaded.","commonSituations":"A stale persistent browser session whose cookies expired so grok.com serves a login redirect; Cloudflare bot challenges after an IP/VPN change; Grok free-tier message limit reached so the composer is disabled; Grok shipping a DOM change that breaks the composer selectors; another chat still streaming, leaving the send control disabled.","solutions":["Re-authenticate the grok.com session (run the site's login/auth command or log in in the persistent browser) — a stale or challenged session is the most common cause, per the attached SESSION_HINT.","Re-run with the `--new` flag to start a fresh chat, which avoids a busy composer left over from a still-streaming previous turn.","Check for Cloudflare/human-verification challenges or rate-limit banners on grok.com in the browser session and clear them manually.","Wait and retry later if the free-tier usage cap disabled the send button.","If it persists after re-login, the composer DOM selectors may be outdated — update the sendMessage implementation in clis/grok/utils.js to match the current grok.com markup."],"exampleFix":"// before\nconst sendResult = await sendMessage(page, prompt);\nif (!sendResult || !sendResult.ok) {\n    throw new CommandExecutionError(`${reason}${detail}`, SESSION_HINT);\n}\n// after: start a clean chat and confirm login before sending\nawait startNewChat(page);\nif (!(await isLoggedIn(page))) throw authRequired();\nconst sendResult = await sendMessage(page, prompt);\nif (!sendResult || !sendResult.ok) {\n    throw new CommandExecutionError(`${reason}${detail}`, SESSION_HINT);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const [{ response }] = await run('grok', 'ask', { prompt });\n} catch (e) {\n  if (e instanceof CommandExecutionError && /login|auth|challenge|session/i.test(String(e.hint ?? e.message))) {\n    await run('grok', 'login');          // refresh the browser session, then retry once\n    return await run('grok', 'ask', { prompt, new: true });\n  }\n  throw e;\n}","preventionTips":["Re-authenticate the grok.com session regularly instead of letting cookies lapse.","Use the --new flag when a previous conversation may still be streaming, to avoid a busy composer.","Watch for Cloudflare challenges and clear them manually before running scripted commands.","Track free-tier usage limits and back off when nearing the cap.","After grok.com UI updates, smoke-test one ask command before batch automation."],"tags":["browser-automation","authentication","grok","session-expired"],"backgroundTag":"browser-session-auth-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}