jackwener/OpenCLI · error · Error

需要登录!请先在浏览器中访问 maimai.cn 并登录

Error message

需要登录!请先在浏览器中访问 maimai.cn 并登录

What it means

Thrown inside the browser-context fetch in clis/maimai/search-talents.js:117 when the talent-search API responds 401/403 or body error_code 20002 — Maimai's 'not logged in / session invalid' code. The Chinese message tells the user to visit maimai.cn in the browser and log in first, because the search relies on the browser's authenticated cookies plus a matching csrftoken.

Source

Thrown at clis/maimai/search-talents.js:117

      const res = await fetch('https://maimai.cn/api/ent/discover/search?channel=www&data_version=3.0&version=1.0.0', {
        method: 'POST',
        headers: {
          'accept': '*/*',
          'content-type': 'text/plain;charset=UTF-8',
          'origin': 'https://maimai.cn',
          'referer': 'https://maimai.cn/ent/talents/discover/search_v2',
          'x-csrf-token': csrftoken,
        },
        credentials: 'include',
        body: JSON.stringify(body),
      });

      const result = await res.json();

      // Check login status
      if (res.status === 401 || res.status === 403 || result.error_code === 20002) {
        throw new Error('需要登录!请先在浏览器中访问 maimai.cn 并登录');
      }

      if (result.code !== 200 && result.code !== 0) {
        throw new Error(result.message || result.error || 'API 请求失败');
      }

      return result;
    }`);

    if (!data || typeof data !== 'object' || Array.isArray(data)) {
      throw new CommandExecutionError('Maimai search returned malformed API payload');
    }

    // Extract talent list from response. Missing list fields mean the API
    // shape drifted; only an explicit empty array is a true empty result.
    const talentListCandidates = [
      data.data?.list,
      data.data?.talent_list,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open https://maimai.cn/ in the CLI's browser and log in, then re-run the search
  2. After re-login, retry so a fresh csrftoken cookie is read via CDP
  3. If cookies look valid but 20002 persists, verify the account has talent-search (招聘) access
  4. Check that the csrftoken cookie exists; clear cookies and log in again if it's stale

Example fix

// before (stale csrf after re-login)
const csrftoken = cookies.find(c => c.name === 'csrftoken')?.value || '';
// after: refresh session and csrf before searching
await page.goto('https://maimai.cn/');
const cookies = await page.getCookies({ url: 'https://maimai.cn' });
const csrftoken = cookies.find(c => c.name === 'csrftoken')?.value || '';
if (!csrftoken) throw new Error('需要登录!请先在浏览器中访问 maimai.cn 并登录');
Defensive patterns

Strategy: try-catch

Validate before calling

// before searching, verify an authenticated session + csrf token
const cookies = await page.getCookies({ url: 'https://maimai.cn' });
if (!cookies.some(c => c.name === 'csrftoken')) {
  throw new Error('需要登录:请先在浏览器中访问 maimai.cn 并登录');
}

Type guard

function isMaimaiAuthFailure(e) {
  return e instanceof Error && /需要登录|error_code.*20002/i.test(e.message);
}

Try / catch

try {
  await searchTalents(page, query);
} catch (e) {
  if (isMaimaiAuthFailure(e)) {
    console.error('Session expired — log in at maimai.cn in the browser, then retry');
    return { needsLogin: true };
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `maimai search-talents <query>` with an anonymous or expired session cookie, a csrftoken that doesn't match the session (stale cookie after re-login), or Maimai revoking the session server-side (error_code 20002 even with HTTP 200).

Common situations: Maimai session expired overnight; user logged out or logged in elsewhere invalidating the session; cookies cleared; csrftoken cookie rotated so the x-csrf-token header no longer matches; enterprise talent-search access not enabled for the account.

Related errors


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