jackwener/OpenCLI · error · ArgumentError
xianyu messages accepts either item_id/user_id or --rank, no
Error message
xianyu messages accepts either item_id/user_id or --rank, not both
What it means
The `xianyu messages` command supports two mutually exclusive targeting modes: an explicit item_id+user_id pair, or a `--rank` index pointing at a conversation from a prior `xianyu inbox` listing. Passing both at once is ambiguous, so ArgumentError is thrown from clis/xianyu/messages.js:37. It is an input-validation error, not a runtime/API failure.
Source
Thrown at clis/xianyu/messages.js:37
access: 'read',
description: '读取指定闲鱼私信会话的最近聊天内容',
domain: 'www.goofish.com',
strategy: Strategy.COOKIE,
navigateBefore: false,
browser: true,
args: [
{ name: 'item_id', positional: true, help: '闲鱼商品 item_id' },
{ name: 'user_id', positional: true, help: '聊一聊对方的 user_id / peerUserId' },
{ name: 'limit', type: 'int', default: DEFAULT_MESSAGE_LIMIT, help: 'Number of visible messages to return' },
{ name: 'rank', type: 'int', default: 0, help: 'Conversation rank from xianyu inbox; clicks the visible row instead of requiring IDs' },
],
columns: ['index', 'peer_name', 'item_title', 'message', 'item_id', 'peer_user_id', 'url'],
func: async (page, kwargs) => {
const hasItemId = kwargs.item_id != null && kwargs.item_id !== '';
const hasUserId = kwargs.user_id != null && kwargs.user_id !== '';
const rank = normalizeRank(kwargs.rank);
if (rank > 0 && (hasItemId || hasUserId)) {
throw new ArgumentError('xianyu messages accepts either item_id/user_id or --rank, not both');
}
if (rank === 0 && hasItemId !== hasUserId) {
throw new ArgumentError('xianyu messages requires both item_id and user_id, or --rank from xianyu inbox');
}
if (rank === 0 && !hasItemId && !hasUserId) {
throw new ArgumentError('xianyu messages requires item_id/user_id or --rank from xianyu inbox');
}
const hasIds = hasItemId && hasUserId;
const itemId = hasIds ? normalizeNumericId(kwargs.item_id, 'item_id', '1038951278192') : '';
const userId = hasIds ? normalizeNumericId(kwargs.user_id, 'user_id', '3650092411') : '';
const limit = normalizeLimit(kwargs.limit, DEFAULT_MESSAGE_LIMIT, MAX_MESSAGE_LIMIT, 'messages --limit');
let url = '';
if (hasIds) {
url = buildChatUrl(itemId, userId);
await page.goto(url);
} else {
if (!page.getCurrentUrl || !/https:\/\/www\.goofish\.com\/im\b/.test(await page.getCurrentUrl())) {
await page.goto('https://www.goofish.com/im');View on GitHub (pinned to 49907e53dc)
Solutions
- Pick one targeting mode: either pass --rank N (from xianyu inbox output) OR pass both --item_id and --user_id, never both styles.
- Remove the --rank flag if you intend to address the conversation by IDs.
- Remove --item_id/--user_id if you intend to pick the Nth inbox conversation by rank.
- In wrapper scripts, conditionally build the argument list based on which mode was selected.
Example fix
// before await cli.run(['xianyu', 'messages', '--rank', '2', '--item_id', itemId, '--user_id', userId]); // after const args = byRank ? ['xianyu', 'messages', '--rank', String(rank)] : ['xianyu', 'messages', '--item_id', itemId, '--user_id', userId]; await cli.run(args);
Defensive patterns
Strategy: validation
Validate before calling
const modes = [rank > 0, Boolean(itemId || userId)].filter(Boolean).length;
if (modes > 1) throw new Error('use --rank OR item_id+user_id, not both'); Try / catch
try {
await cli.run(args);
} catch (e) {
if (e instanceof ArgumentError && /not both/.test(e.message)) {
console.error('Fix invocation: drop --rank or drop --item_id/--user_id');
} else throw e;
} Prevention
- Build CLI args in a single helper that enforces one targeting mode.
- Never forward leftover flags between invocations in scripts.
- Document the two targeting modes where the command is wrapped.
When it happens
Trigger: Invoking the messages command with --rank greater than 0 while also supplying item_id and/or user_id, e.g. `xianyu messages --rank 2 --item_id 123 --user_id 456` or `--rank 1 --item_id 123`.
Common situations: Scripting a flow that iterates inbox results by rank but forgot to remove leftover item_id/user_id flags from a previous invocation; copy-pasting example commands and merging both argument styles; templated commands where optional kwargs are filled in unconditionally.
Related errors
- xianyu messages requires both item_id and user_id, or --rank
- xianyu messages requires item_id/user_id or --rank from xian
- xianyu reply accepts either item_id/user_id or --rank, not b
- xianyu reply requires both item_id and user_id, or --rank fr
- xianyu reply requires item_id/user_id or --rank from xianyu
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/74c692901d1a25f8.
Report an issue: GitHub.