jackwener/OpenCLI · error · CommandExecutionError

Unexpected zsxq probe: ${JSON.stringify(probe)}

Error message

Unexpected zsxq probe: ${JSON.stringify(probe)}

What it means

If the probe result has none of the recognized kinds (auth/http/exception/ok), verifyZsxqIdentity throws CommandExecutionError('Unexpected zsxq probe: ...') containing the JSON of the whole probe object. This is a defensive branch for malformed or unclassified probe outcomes — effectively an internal invariant violation.

Source

Thrown at clis/zsxq/auth.js:39

        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 {
        const r = await fetch('https://api.zsxq.com/v2/users/self', { credentials: 'include', headers: { Accept: 'application/json' } });

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the JSON dump in the message to see the actual probe shape.
  2. Upgrade/downgrade the library so the probe script and dispatcher are from the same version.
  3. Re-run the command — transient serialization failures in the browser context can produce empty results.
  4. If reproducible, log page content and report the probe output as a bug to the library maintainers.

Example fix

// before
const id = await verifyZsxqIdentity(page); // throws Unexpected probe
// after
let id;
try { id = await verifyZsxqIdentity(page); }
catch (e) {
  if (e.message.includes('Unexpected zsxq probe')) {
    id = await verifyZsxqIdentity(await page.context().newPage()); // retry on a fresh page
  } else throw e;
}
Defensive patterns

Strategy: retry

Type guard

const isUnexpectedProbe = (e) => (e?.message || '').includes('Unexpected zsxq probe:');

Try / catch

try {
  return await verifyZsxqIdentity(page);
} catch (e) {
  if (isUnexpectedProbe(e)) {
    const fresh = await page.context().newPage();
    try { return await verifyZsxqIdentity(fresh); }
    finally { await fresh.close(); }
  }
  throw e;
}

Prevention

When it happens

Trigger: The page-injected probe script returns an object without a recognized 'kind' field, e.g. due to a version mismatch between the probe script and this dispatcher, or the script's return value being altered/undefined-shaped.

Common situations: Running mismatched library versions where the probe contract changed; browser serialization quirks stripping fields from the injected script's return value; custom patches to the probe code.

Related errors


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