jackwener/OpenCLI · error · CommandExecutionError

zsxq whoami failed: ${probe.detail}

Error message

zsxq whoami failed: ${probe.detail}

What it means

The probe wraps its fetch logic in a try/catch inside the page; any exception thrown there (network failure, JSON parse error, runtime error) is returned as kind:'exception' and re-thrown as CommandExecutionError with the inner message. It means the whoami check itself crashed rather than returning an HTTP status.

Source

Thrown at clis/zsxq/auth.js:38

        });
        if (r.status === 401 || r.status === 403) {
          return { kind: 'auth', detail: 'zsxq /v2/users/self returned HTTP ' + r.status };
        }
        if (!r.ok) return { kind: 'http', httpStatus: r.status };
        const d = await r.json();
        if (d?.succeeded === false || !d?.resp_data?.user) {
          return { kind: 'auth', detail: 'zsxq /v2/users/self returned succeeded=false — anonymous' };
        }
        const u = d.resp_data.user;
        return { ok: true, user_id: String(u.user_id || u.id || ''), name: String(u.name || u.nickname || '') };
      } catch (e) {
        return { kind: 'exception', detail: String(e && e.message || e) };
      }
    })()
  `);
  if (probe?.kind === 'auth') throw new AuthRequiredError('zsxq.com', probe.detail);
  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from zsxq /v2/users/self`);
  if (probe?.kind === 'exception') throw new CommandExecutionError(`zsxq whoami failed: ${probe.detail}`);
  if (!probe?.ok) throw new CommandExecutionError(`Unexpected zsxq probe: ${JSON.stringify(probe)}`);
  if (!probe.user_id) {
    throw new AuthRequiredError('zsxq.com', 'zsxq /v2/users/self 200 but user_id missing — incomplete session');
  }
  return { user_id: probe.user_id, name: probe.name };
}

registerSiteAuthCommands({
  site: 'zsxq',
  domain: 'zsxq.com',
  loginUrl: 'https://wx.zsxq.com/login',
  columns: ['user_id', 'name'],
  verify: verifyZsxqIdentity,
  // No-navigation poll: probe the API from the current page so the login-page
  // QR code isn't reset by a goto on every interval.
  poll: async (page) => {
    const loggedIn = await page.evaluate(`(async () => {
      try {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read probe.detail in the message to identify the underlying exception (TypeError: fetch failed, JSON parse error, etc.).
  2. Verify network connectivity and DNS resolution for api.zsxq.com from the machine running the browser.
  3. Check whether the response is HTML instead of JSON — usually a redirect to a login page; establish a logged-in session first.
  4. Re-run the probe after ensuring the page is on a zsxq.com origin so the fetch carries proper cookies.

Example fix

// before
const who = await verifyZsxqIdentity(page);
// after
try {
  const who = await verifyZsxqIdentity(page);
} catch (e) {
  if (e.message.startsWith('zsxq whoami failed')) {
    console.error('probe detail:', e.message);
    await page.goto('https://zsxq.com', { waitUntil: 'domcontentloaded' });
    return verifyZsxqIdentity(page);
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: confirm api.zsxq.com is reachable from the browser context
await page.goto('https://api.zsxq.com', { waitUntil: 'domcontentloaded', timeout: 15000 });

Type guard

const isWhoamiFailure = (e) => (e?.message || '').startsWith('zsxq whoami failed:');

Try / catch

try {
  return await verifyZsxqIdentity(page);
} catch (e) {
  if (isWhoamiFailure(e)) {
    console.error('probe exception:', e.message);
    await page.goto('https://zsxq.com', { waitUntil: 'domcontentloaded' });
    return verifyZsxqIdentity(page);
  }
  throw e;
}

Prevention

When it happens

Trigger: fetch() to /v2/users/self throws (DNS failure, connection refused, CORS/network error), or r.json() fails on a non-JSON response (e.g. an HTML login page or proxy error page).

Common situations: No network connectivity; corporate proxy returning HTML error pages; zsxq serving an HTML redirect instead of JSON; page navigation destroying the execution context mid-probe.

Related errors


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