jackwener/OpenCLI · warning · CommandExecutionError

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

Error message

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

What it means

This TimeoutError is thrown when `twitter bookmark` clicked the bookmark action but could not confirm within 1s that it took effect (result.unconfirmed was true, meaning writeStarted). Since the write may already have happened, retrying blindly could toggle the bookmark off; the CLI surfaces the ambiguity instead of guessing.

Source

Thrown at clis/12306/auth.js:42

      }
      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' };
      }
      const userName = d.data?.user_name || d.data?.userName || d.user_name || '';
      if (!userName) {
        return { kind: 'auth', detail: '12306 initMy12306Api 200 but no user_name surface' };
      }
      return { ok: true, user_name: String(userName) };
    } catch (e) {
      return { kind: 'exception', detail: String(e && e.message || e) };
    }
  })()`);
  if (probe?.kind === 'auth') throw new AuthRequiredError('12306.cn', probe.detail);
  if (probe?.kind === 'exception') throw new CommandExecutionError(`12306 whoami failed: ${probe.detail}`);
  if (!probe?.ok) throw new CommandExecutionError(`Unexpected 12306 probe: ${JSON.stringify(probe)}`);
  return { user_name: probe.user_name };
}

registerSiteAuthCommands({
  site: '12306',
  domain: '12306.cn',
  loginUrl: 'https://kyfw.12306.cn/otn/resources/login.html',
  columns: ['user_name'],
  quickCheck: has12306SessionCookie,
  verify: verify12306Identity,
  poll: async (page) => {
    if (!await has12306SessionCookie(page)) {
      throw new AuthRequiredError('12306.cn', 'Waiting for 12306 tk auth cookie');
    }
    return verify12306Identity(page);
  },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open the tweet in the browser and check whether the bookmark icon is already filled before doing anything
  2. If not bookmarked, simply retry the command once
  3. If it was already bookmarked, do nothing — retrying would un-bookmark it
  4. If it recurs, refresh the page and retry; persistent failure suggests a selector change needing a CLI update

Example fix

// before
throw new TimeoutError('twitter bookmark confirmation', 1, `${result.message} ...`);
// after
const isBookmarked = await page.evaluate(`!!document.querySelector('[data-testid="bookmark"][aria-pressed="true"], [data-testid="removeBookmark"]')`);
if (isBookmarked) return [{ status: 'success', message: 'already bookmarked' }];
// otherwise retry the bookmark action
Defensive patterns

Strategy: retry

Validate before calling

const isBookmarked = await page.evaluate(`!!document.querySelector('[data-testid="removeBookmark"]')`);
if (isBookmarked) return; // already bookmarked — don't retry or you'll un-bookmark

Type guard

function isUnconfirmed(r) { return r && typeof r === 'object' && r.unconfirmed === true; }

Try / catch

try {
  await opencli('twitter bookmark', url);
} catch (e) {
  if (e instanceof TimeoutError && /twitter bookmark confirmation/.test(e.message)) {
    // check the tweet's bookmark state in the browser before any retry
  }
}

Prevention

When it happens

Trigger: The in-page script set writeStarted, clicked the bookmark button, but the post-click state check (aria-pressed/testid) did not flip within 1s — slow render, stale button selector, or the tweet page hadn't fully hydrated.

Common situations: Slow connection or heavy DOM on long tweet threads; already-bookmarked tweets where the button state doesn't change; Twitter UI variant A/B tests changing testids; running on a loaded/throttled machine.

Related errors


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