jackwener/OpenCLI · error · CommandExecutionError

Reuters whoami failed

Error message

Reuters whoami failed: ${probe.detail}

What it means

verifyReutersIdentity runs an in-page whoami probe via page.evaluate; if the probe throws (a JS exception inside the page or in the injected script), the result has kind 'exception' and the code wraps it in a CommandExecutionError. The library throws this because it cannot determine the Reuters identity when the probe script fails to execute, distinguishing it from an explicit auth wall.

Solutions

  1. Retry the identity verification after re-loading https://www.reuters.com fully (increase wait time after page.goto).
  2. Check the probe.detail in the message — it names the in-page error; fix the underlying cause (e.g. consent-wall, CSP, blocked localStorage).
  3. Ensure the user is logged in first; run the login/wait flow that throws AuthRequiredError before calling verifyReutersIdentity.
  4. If Reuters changed its page, update the whoami script to match the current site.

Example fix

// before
const who = await verifyReutersIdentity(page);
// after
let who;
try {
  who = await verifyReutersIdentity(page);
} catch (e) {
  await page.goto('https://www.reuters.com');
  await page.wait(5);
  who = await verifyReutersIdentity(page);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling, ensure the page is on reuters.com and loaded
if (!page.url().includes('reuters.com')) await page.goto('https://www.reuters.com');
await page.wait(3);

Type guard

function isProbeResult(p) {
  return p != null && typeof p === 'object' &&
    (p.kind === 'auth' || p.kind === 'exception' || p.ok === true);
}

Try / catch

try {
  const who = await verifyReutersIdentity(page);
} catch (e) {
  if (e instanceof AuthRequiredError) {
    // prompt login
  } else if (/Reuters whoami failed/.test(e.message)) {
    // in-page exception: reload page and retry once
    await page.goto('https://www.reuters.com');
    await page.wait(5);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: The injected whoami script (executed via page.evaluate) throws an exception — e.g. localStorage access blocked, JSON parse failure on an unexpected response shape, or a runtime error in the page script — so probe.kind === 'exception' at clis/reuters/auth.js:42.

Common situations: Reuters page loaded in a broken/incomplete state before the script ran; browser context with localStorage disabled or restricted by cookie-consent overlays; a Reuters DOM/API change breaking the whoami script; anti-bot interstitial replacing the page content.

Related errors


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

Appendix: source

Thrown at clis/reuters/auth.js:42

            const u = JSON.parse(localStorage.getItem(oidcKey) || '{}');
            cuid = String(u?.profile?.cuid || u?.profile?.sub || '');
          } catch {}
        }
        if (!cuid) {
          const ajs = localStorage.getItem('ajs_user_id');
          if (ajs && ajs !== 'null') cuid = ajs;
        }
        if (!cuid) {
          return { kind: 'auth', detail: 'Reuters logged-in but cuid missing — session shape drifted' };
        }
        return { ok: true, user_id: cuid, subscribed: Boolean(subState.isSubscribed) };
      } catch (e) {
        return { kind: 'exception', detail: String(e && e.message || e) };
      }
    })()
  `);
  if (probe?.kind === 'auth') throw new AuthRequiredError('reuters.com', probe.detail);
  if (probe?.kind === 'exception') throw new CommandExecutionError(`Reuters whoami failed: ${probe.detail}`);
  if (!probe?.ok) throw new CommandExecutionError(`Unexpected Reuters probe: ${JSON.stringify(probe)}`);
  return { user_id: probe.user_id, subscribed: probe.subscribed };
}

registerSiteAuthCommands({
  site: 'reuters',
  domain: 'reuters.com',
  loginUrl: 'https://www.reuters.com/account/sign-in/',
  columns: ['user_id', 'subscribed'],
  verify: verifyReutersIdentity,
  // No-navigation poll: check localStorage on the current page so login-flow
  // polling doesn't bounce the user off the sign-in page every interval.
  poll: async (page) => {
    const loggedIn = await page.evaluate(`(() => {
      try {
        const raw = localStorage.getItem('rcom-subscription-state');
        return raw ? JSON.parse(raw).isLoggedIn === true : false;
      } catch { return false; }

View on GitHub (pinned to 49907e53dc)