{"record":{"id":"82ac54c70b65cf64","repo":"jackwener/OpenCLI","slug":"xianyu-messages-requires-item-id-user-id-or-rank","errorCode":null,"errorMessage":"xianyu messages requires item_id/user_id or --rank from xianyu inbox","messagePattern":"xianyu messages requires item_id/user_id or --rank from xianyu inbox","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/messages.js","lineNumber":43,"sourceCode":"    args: [\n        { name: 'item_id', positional: true, help: '闲鱼商品 item_id' },\n        { name: 'user_id', positional: true, help: '聊一聊对方的 user_id / peerUserId' },\n        { name: 'limit', type: 'int', default: DEFAULT_MESSAGE_LIMIT, help: 'Number of visible messages to return' },\n        { name: 'rank', type: 'int', default: 0, help: 'Conversation rank from xianyu inbox; clicks the visible row instead of requiring IDs' },\n    ],\n    columns: ['index', 'peer_name', 'item_title', 'message', 'item_id', 'peer_user_id', 'url'],\n    func: async (page, kwargs) => {\n        const hasItemId = kwargs.item_id != null && kwargs.item_id !== '';\n        const hasUserId = kwargs.user_id != null && kwargs.user_id !== '';\n        const rank = normalizeRank(kwargs.rank);\n        if (rank > 0 && (hasItemId || hasUserId)) {\n            throw new ArgumentError('xianyu messages accepts either item_id/user_id or --rank, not both');\n        }\n        if (rank === 0 && hasItemId !== hasUserId) {\n            throw new ArgumentError('xianyu messages requires both item_id and user_id, or --rank from xianyu inbox');\n        }\n        if (rank === 0 && !hasItemId && !hasUserId) {\n            throw new ArgumentError('xianyu messages requires item_id/user_id or --rank from xianyu inbox');\n        }\n        const hasIds = hasItemId && hasUserId;\n        const itemId = hasIds ? normalizeNumericId(kwargs.item_id, 'item_id', '1038951278192') : '';\n        const userId = hasIds ? normalizeNumericId(kwargs.user_id, 'user_id', '3650092411') : '';\n        const limit = normalizeLimit(kwargs.limit, DEFAULT_MESSAGE_LIMIT, MAX_MESSAGE_LIMIT, 'messages --limit');\n        let url = '';\n        if (hasIds) {\n            url = buildChatUrl(itemId, userId);\n            await page.goto(url);\n        } else {\n            if (!page.getCurrentUrl || !/https:\\/\\/www\\.goofish\\.com\\/im\\b/.test(await page.getCurrentUrl())) {\n                await page.goto('https://www.goofish.com/im');\n            }\n        }\n        await page.wait(2);\n        if (rank > 0) {\n            requireClickResult(await page.evaluate(buildClickInboxConversationEvaluate(rank - 1)), 'messages rank click');\n            await page.wait(2);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/messages.js#L25-L61","documentation":"When neither --rank nor any targeting ID is provided (rank === 0, no item_id, no user_id), `xianyu messages` has no way to identify a conversation and throws ArgumentError at clis/xianyu/messages.js:43. The command deliberately does not guess a default conversation; the caller must specify one.","triggerScenarios":"Running bare `xianyu messages` with no flags, or with flags whose values are null/empty strings so hasItemId/hasUserId evaluate false.","commonSituations":"Forgetting that messages requires explicit targeting (unlike `xianyu inbox`, which lists conversations); a wrapper dropping kwargs with empty values before exec; empty-string env/config variables feeding '' into the CLI.","solutions":["Pass --item_id and --user_id, or --rank N referencing a conversation from xianyu inbox output.","Run `xianyu inbox` first to obtain ranked conversations, then call messages with --rank.","Check that your caller isn't stripping or emptying kwargs (null and '' both count as missing).","Add a pre-invocation check that at least one valid targeting mode is populated."],"exampleFix":"// before\nawait cli.run(['xianyu', 'messages']);\n\n// after\nconst conv = (await cli.run(['xianyu', 'inbox']))[0];\nawait cli.run(['xianyu', 'messages', '--item_id', conv.item_id, '--user_id', conv.peer_user_id]);","handlingStrategy":"validation","validationCode":"const hasTarget = rank > 0 || (itemId && userId);\nif (!hasTarget) throw new Error('xianyu messages needs --rank or item_id+user_id');","typeGuard":null,"tryCatchPattern":"try {\n  await runMessages(args);\n} catch (e) {\n  if (e instanceof ArgumentError && /requires item_id\\/user_id or --rank/.test(e.message)) {\n    console.error('No targeting specified — run `xianyu inbox` first, then pass --rank or IDs');\n  } else throw e;\n}","preventionTips":["Always run xianyu inbox first in automated flows and thread rank/IDs through.","Filter out null/empty kwargs before building the command line.","Add a wrapper that defaults to inbox rank 1 when no target is given."],"tags":["argument-validation","cli-usage","xianyu"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}