jackwener/OpenCLI · error · AuthRequiredError

${result.detail}

Error message

${result.detail}

What it means

During the Gmail identity probe, the in-page script can return a result tagged kind:'auth' with a detail string; verifyGmailIdentity converts that into AuthRequiredError(GMAIL_HOST, result.detail). The generic template "${result.detail}" means the concrete message comes from the page probe — typically that the account control showed a signed-out/login state.

Source

Thrown at clis/gmail/auth.js:35

  const result = unwrapBrowserResult(await page.evaluate(`(() => {
    const account = Array.from(document.querySelectorAll('a[aria-label], button[aria-label]'))
      .map((node) => String(node.getAttribute('aria-label') || '').trim())
      .find((label) => /@/.test(label) && /(google account|google 帐号|google 账号)/i.test(label));
    if (!account) {
      const login = document.querySelector('a[href*="accounts.google.com/ServiceLogin"], input[type="email"]');
      return login
        ? { kind: 'auth', detail: 'Gmail shows a Google sign-in surface' }
        : { kind: 'shape', detail: 'Gmail account control was not found' };
    }
    const email = account.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i)?.[0] || '';
    const beforeEmail = email ? account.slice(0, account.indexOf(email)) : account;
    const name = beforeEmail
      .replace(/^.*?(?:google account|google 帐号|google 账号)\s*[::]?\s*/i, '')
      .replace(/[,((]\s*$/, '')
      .trim();
    return email ? { ok: true, email, name } : { kind: 'shape', detail: 'Gmail account control did not expose an email address' };
  })()`), 'identity probe');
  if (result?.kind === 'auth') throw new AuthRequiredError(GMAIL_HOST, result.detail);
  if (!result?.ok) throw new CommandExecutionError(result?.detail || 'Gmail identity probe returned an unexpected result');
  return { email: result.email, name: result.name || null };
}

registerSiteAuthCommands({
  site: 'gmail',
  domain: GMAIL_HOST,
  loginUrl: 'https://accounts.google.com/ServiceLogin?service=mail&continue=https%3A%2F%2Fmail.google.com%2Fmail%2Fu%2F0%2F%23inbox',
  columns: ['email', 'name'],
  quickCheck: hasGoogleSession,
  verify: verifyGmailIdentity,
  poll: verifyGmailIdentity,
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-authenticate: open Gmail in the browser and complete sign-in / account selection
  2. Clear Google cookies and log in fresh if cookies are stale
  3. Verify page.goto landed on the expected /mail/u/<index>/ origin, not a login redirect
  4. Catch AuthRequiredError and drive the registered gmail login flow before retrying

Example fix

// before
const identity = await verifyGmailIdentity(page);
// after
try {
  const identity = await verifyGmailIdentity(page);
} catch (e) {
  if (e instanceof AuthRequiredError) {
    await loginSite('gmail');
    const identity = await verifyGmailIdentity(page);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const url = page.url?.() ?? '';
if (/accounts\.google\.com|\/login/.test(url)) {
  throw new Error('Gmail redirected to login — re-authenticate before probing identity');
}

Type guard

function isAuthProbeResult(r) {
  return !!r && typeof r === 'object' && ('ok' in r || 'kind' in r);
}

Try / catch

try {
  const identity = await verifyGmailIdentity(page);
} catch (e) {
  if (e instanceof AuthRequiredError) {
    await driveGmailLoginFlow(page);
    return verifyGmailIdentity(page);
  }
  throw e;
}

Prevention

When it happens

Trigger: The page.evaluate identity probe returns { kind: 'auth', detail: ... } — e.g. the probe detected a 'Sign in' button or login redirect in the Gmail UI instead of an authenticated account control.

Common situations: Google session cookies exist but the Gmail page still rendered signed-out (stale cookies, session revoked server-side); account picker requiring re-auth; Gmail redirected to a login/choose-account URL; cookie present but for a different Google account than expected.

Related errors


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