jackwener/OpenCLI · error · CommandExecutionError

Claude whoami failed: ${result.detail}

Error message

Claude whoami failed: ${result.detail}

What it means

This CommandExecutionError wraps any JavaScript exception thrown inside the in-page fetch probe to /api/organizations (the caught error is stringified into result.detail). It indicates the whoami verification script itself crashed in the browser context rather than receiving a normal HTTP response — e.g. a failed fetch (network/DNS error), JSON parsing failure, or a Claude page change that breaks the script.

Source

Thrown at clis/claude/auth.js:36

      if (res.status === 401 || res.status === 403) {
        return { kind: 'auth', detail: 'Claude /api/organizations HTTP ' + res.status };
      }
      if (!res.ok) return { kind: 'http', httpStatus: res.status };
      const d = await res.json();
      if (!Array.isArray(d) || d.length === 0) {
        return { kind: 'auth', detail: 'Claude /api/organizations empty' };
      }
      const userIdCookie = (document.cookie.split('; ').find(c => c.startsWith('ajs_user_id=')) || '').split('=')[1] || '';
      const activeOrgCookie = (document.cookie.split('; ').find(c => c.startsWith('lastActiveOrg=')) || '').split('=')[1] || '';
      const activeOrg = d.find(o => o.uuid === activeOrgCookie) || d[0];
      return { ok: true, user_id: userIdCookie, org_name: activeOrg.name || '', org_uuid: activeOrg.uuid || '' };
    } catch (e) {
      return { kind: 'exception', detail: String(e && e.message || e) };
    }
  })()`);
  if (result?.kind === 'auth') throw new AuthRequiredError('claude.ai', result.detail);
  if (result?.kind === 'http') throw new CommandExecutionError(`HTTP ${result.httpStatus} from /api/organizations`);
  if (result?.kind === 'exception') throw new CommandExecutionError(`Claude whoami failed: ${result.detail}`);
  if (!result?.ok) throw new CommandExecutionError(`Unexpected Claude probe: ${JSON.stringify(result)}`);
  if (!result.user_id) throw new AuthRequiredError('claude.ai', 'Claude session incomplete — ajs_user_id cookie missing');
  return { user_id: String(result.user_id), org_name: String(result.org_name), org_uuid: String(result.org_uuid) };
}

registerSiteAuthCommands({
  site: 'claude',
  domain: 'claude.ai',
  loginUrl: 'https://claude.ai/login',
  columns: ['user_id', 'org_name', 'org_uuid'],
  quickCheck: hasClaudeSessionCookie,
  verify: verifyClaudeIdentity,
  poll: async (page) => {
    if (!await hasClaudeSessionCookie(page)) {
      throw new AuthRequiredError('claude.ai', 'Waiting for Claude sessionKey cookie');
    }
    return verifyClaudeIdentity(page);
  },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read result.detail in the message to see the underlying exception and address it specifically
  2. Verify general internet connectivity and that https://claude.ai loads in the browser without a Cloudflare challenge
  3. Disable conflicting extensions (ad-blockers/script blockers) or bypass VPN/proxy, then retry
  4. Re-run the login flow (`opencli claude auth`) so the probe runs on a freshly loaded claude.ai page
  5. Update the library — Claude may have changed its response format and a newer probe handles it

Example fix

// before
const res = await fetch('/api/organizations', { credentials: 'include' }); // TypeError: Failed to fetch (offline)
// after
// ensure connectivity first, then retry:
ping claude.ai && opencli claude whoami
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure connectivity before running browser probes
const res = await fetch('https://claude.ai/robots.txt').catch(() => null);
if (!res || !res.ok) throw new Error('claude.ai unreachable — check network/VPN/proxy');

Type guard

function isProbeException(result) {
  return !!result && result.kind === 'exception' && typeof result.detail === 'string';
}

Try / catch

try {
  const identity = await verifyClaudeIdentity(page);
} catch (e) {
  if (e.message.startsWith('Claude whoami failed:')) {
    console.error('Probe crashed in page:', e.message);
    // check network, disable interfering extensions, reload page and retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: The page.evaluate probe's try block throws: network failure reaching /api/organizations (offline, DNS failure, proxy block), res.json() failing on a non-JSON response (login redirect HTML, Cloudflare challenge page), or an injected script/CSP change breaking evaluation.

Common situations: Corporate proxy or VPN blocking claude.ai API calls; Cloudflare interstitial returning HTML so JSON parsing throws; internet drop mid-probe; browser extension or CSP changes blocking in-page fetch; Claude frontend returning an unexpected payload shape after an update.

Related errors


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