jackwener/OpenCLI · error · AuthRequiredError

grok.com

Error message

grok.com

What it means

verifyGrokIdentity() (the grok site's auth 'whoami'/verify step) throws AuthRequiredError('grok.com', 'Grok __Secure-next-auth.session-token cookie missing') when the browser session's cookies for https://grok.com contain no non-empty __Secure-next-auth.session-token. That NextAuth session cookie is the library's quick, local check that the user is logged in to grok.com; without it every grok command would be anonymous. The error tells the user to perform the interactive site login flow before using grok commands.

Solutions

  1. Run the grok site login flow (loginUrl https://grok.com/auth/sign-in, e.g. the registered `grok login` command) and complete sign-in interactively in the managed browser.
  2. After logging in, re-run the auth verify/whoami command to confirm __Secure-next-auth.session-token is present and /api/auth/session returns a user.
  3. If you log in manually, use the same persistent browser profile the CLI uses so the cookie lands in the right store.
  4. Check you are not in an incognito/profile-wiping setup that discards __Secure- cookies between runs.

Example fix

// before: verify against a session that was never logged in
const identity = await grokWhoami(); // AuthRequiredError
// after: run the login flow first
await grokLogin(); // opens https://grok.com/auth/sign-in and polls until session cookie exists
const identity = await grokWhoami();
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking grok commands, check the session cookie in the persistent profile.
const cookies = await page.getCookies({ url: 'https://grok.com' });
const hasSession = cookies.some(c => c.name === '__Secure-next-auth.session-token' && c.value);
if (!hasSession) {
  await run('grok', 'login'); // interactive sign-in before any grok command
}

Try / catch

try {
  const who = await run('grok', 'whoami');
} catch (e) {
  if (e instanceof AuthRequiredError) {
    await run('grok', 'login');
    return await run('grok', 'whoami');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling any grok auth verify/whoami flow (or registerSiteAuthCommands login/poll path) when: (1) the persistent browser session was never logged in to grok.com; (2) the session cookie expired or was cleared (browser profile reset, cookie purge, logout elsewhere); (3) get_cookies for url https://grok.com returns cookies but none named '__Secure-next-auth.session-token' (e.g. only anonymous/CF cookies); (4) the cookie exists but with an empty value, which the hasGrokSessionCookie check rejects.

Common situations: Fresh environment/container where the persistent profile has no grok.com login; cookies expired after days/weeks since last login; running from a different machine or browser profile than the one used to log in; corporate cookie cleaners or incognito sessions wiping __Secure- cookies; grok.com logout invalidating the stored session.

Related errors


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

Appendix: source

Thrown at clis/grok/auth.js:11

import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';
import { registerSiteAuthCommands } from '../_shared/site-auth.js';

async function hasGrokSessionCookie(page) {
  const cookies = await page.getCookies({ url: 'https://grok.com' });
  return cookies.some(c => c.name === '__Secure-next-auth.session-token' && c.value);
}

async function verifyGrokIdentity(page) {
  if (!await hasGrokSessionCookie(page)) {
    throw new AuthRequiredError('grok.com', 'Grok __Secure-next-auth.session-token cookie missing');
  }
  await page.goto('https://grok.com/');
  await page.wait(2);
  const result = await page.evaluate(`(async () => {
    try {
      const res = await fetch('/api/auth/session', { credentials: 'include', headers: { 'Accept': 'application/json' } });
      if (res.status === 401 || res.status === 403) {
        return { kind: 'auth', detail: 'Grok /api/auth/session HTTP ' + res.status };
      }
      if (!res.ok) return { kind: 'http', httpStatus: res.status };
      const d = await res.json();
      const user = d && d.user;
      if (!user || !user.id) {
        return { kind: 'auth', detail: 'Grok /api/auth/session has no user — anonymous' };
      }
      return { ok: true, user_id: String(user.id), name: String(user.name || '') };
    } catch (e) {
      return { kind: 'exception', detail: String(e && e.message || e) };

View on GitHub (pinned to 49907e53dc)