jackwener/OpenCLI · error · AuthRequiredError

12306 tk auth cookie missing

Error message

12306 tk auth cookie missing

What it means

AuthRequiredError thrown when `twitter bookmark-folders` (list command) finds no `ct0` cookie for https://x.com. The command needs the CSRF token from an authenticated session to call the bookmark-folders GraphQL endpoint, so it fails fast before making any request.

Source

Thrown at clis/12306/auth.js:11

import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';
import { registerSiteAuthCommands } from '../_shared/site-auth.js';

async function has12306SessionCookie(page) {
  const cookies = await page.getCookies({ url: 'https://kyfw.12306.cn' });
  return cookies.some(c => c.name === 'tk' && c.value);
}

async function verify12306Identity(page) {
  if (!await has12306SessionCookie(page)) {
    throw new AuthRequiredError('12306.cn', '12306 tk auth cookie missing');
  }
  await page.goto('https://kyfw.12306.cn/otn/view/index.html');
  await page.wait(2);
  const probe = await page.evaluate(`(async () => {
    try {
      const r = await fetch('/otn/index/initMy12306Api', {
        method: 'POST',
        credentials: 'include',
        headers: { 'X-Requested-With': 'XMLHttpRequest' },
      });
      if (/login\\.html/.test(r.url)) {
        return { kind: 'auth', detail: '12306 initMy12306Api redirected to login' };
      }
      const t = await r.text();
      let d = null;
      try { d = JSON.parse(t); } catch {}
      if (!d || d.status === false || /未登录|登录超时|NotLogin/i.test(t)) {
        return { kind: 'auth', detail: '12306 initMy12306Api returned NotLogin' };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log into x.com interactively in the CLI's browser session and retry
  2. Ensure the CLI uses the persistent profile containing your x.com login
  3. After login, verify the ct0 cookie exists for x.com (devtools → Application → Cookies)
  4. Keep the session alive; avoid cookie-clearing extensions or scripts

Example fix

// before
opencli twitter bookmark-folders   # not logged in
// after
opencli browser open https://x.com/login   # complete login in this profile
opencli twitter bookmark-folders
Defensive patterns

Strategy: try-catch

Validate before calling

const cookies = await page.getCookies({ url: 'https://x.com' });
if (!cookies.some(c => c.name === 'ct0')) throw new Error('Not logged into x.com');

Type guard

function hasCt0(cookies) { return Array.isArray(cookies) && cookies.some(c => c && c.name === 'ct0' && typeof c.value === 'string' && c.value.length > 0); }

Try / catch

try {
  const folders = await opencli('twitter bookmark-folders');
} catch (e) {
  if (/no ct0 cookie/.test(e.message)) {
    await opencli('browser open', 'https://x.com/login');
    // retry after login
  }
}

Prevention

When it happens

Trigger: Running the listing command with a browser session that has never logged into x.com; cookies cleared; wrong browser profile attached; incognito/non-persistent context.

Common situations: CI or scheduled jobs using a fresh browser context; switching machines or profiles; x.com logged the session out due to suspicious activity, purging cookies.

Related errors


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