{"record":{"id":"d97ecc3b73d0e15a","repo":"jackwener/OpenCLI","slug":"keyword","errorCode":null,"errorMessage":"keyword","messagePattern":"keyword","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/dianping/search.js","lineNumber":107,"sourceCode":"    return { ok: true, rows };\n}\n\ncli({\n    site: 'dianping',\n    name: 'search',\n    access: 'read',\n    description: '大众点评店铺搜索（按关键词 + 城市）',\n    domain: 'www.dianping.com',\n    strategy: Strategy.COOKIE,\n    args: [\n        { name: 'keyword', required: true, positional: true, help: '搜索关键词，例如 \"火锅\"' },\n        { name: 'city', help: '城市名（北京/上海/汕头/beijing/shantou/...）或 cityId 数字。未在静态表中的城市会通过 dianping.com 在线解析。不传则使用 cookie 默认城市' },\n        { name: 'limit', type: 'int', default: 15, help: '返回的店铺数量（最多 15，dianping 单页固定 15 条）' },\n    ],\n    columns: SEARCH_COLUMNS,\n    func: async (page, kwargs) => {\n        const keyword = String(kwargs.keyword || '').trim();\n        if (!keyword) throw new ArgumentError('keyword', 'must be a non-empty string');\n\n        const limit = requireSearchLimit(kwargs.limit);\n\n        const cityId = await wrapDianpingStep(\n            'city resolve',\n            () => resolveCityIdAsync(page, kwargs.city),\n        );\n        const path = cityId\n            ? `/search/keyword/${cityId}/0_${encodeURIComponent(keyword)}`\n            : `/search/keyword/0/0_${encodeURIComponent(keyword)}`;\n        const url = `https://www.dianping.com${path}`;\n\n        await wrapDianpingStep(`search \"${keyword}\" navigation`, async () => {\n            await page.goto(url);\n            await page.wait(2);\n        });\n\n        const result = await wrapDianpingStep(","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dianping/search.js#L89-L125","documentation":"ArgumentError thrown by the dianping search command when the required --keyword argument is missing or an empty/whitespace-only string. The library validates keyword before doing any network work since Dianping search requires a non-empty query term.","triggerScenarios":"Calling the dianping search func with kwargs lacking keyword, or keyword='' / keyword='   ' (String(kwargs.keyword||'').trim() yields empty), e.g. `dianping search --city shanghai` with no --keyword, or passing --keyword \"\" from a script.","commonSituations":"CLI invocation missing the --keyword flag; building kwargs programmatically where an upstream variable was empty; shell quoting swallowing the value (e.g. --keyword \"$Q\" with Q empty); passing the term under a wrong key like 'query' or 'q'.","solutions":["Pass a non-empty keyword: dianping search --keyword \"火锅\".","Check that your wrapper/script maps the search term to the correct `keyword` key in kwargs.","Trim/validate the term before invoking: if (!kw.trim()) skip or prompt for input.","If shell variables supply the value, quote them and guard against empty expansion."],"exampleFix":"// before\nconst kw = process.env.Q; await cli.dianping.search({ keyword: kw }); // Q empty → throws\n// after\nconst kw = (process.env.Q || '').trim();\nif (!kw) throw new Error('set Q to a search term');\nawait cli.dianping.search({ keyword: kw });","handlingStrategy":"validation","validationCode":"const keyword = String(process.argv[kwIdx] || '').trim();\nif (!keyword) { console.error('--keyword is required and must be non-empty'); process.exit(2); }","typeGuard":"function hasKeyword(k) { return typeof k === 'string' && k.trim().length > 0; }","tryCatchPattern":"try { await cli.dianping.search({ keyword, city }); }\ncatch (e) { if (e.name === 'ArgumentError' && e.field === 'keyword') { console.error('usage: dianping search --keyword \"<term>\"'); process.exitCode = 2; } else throw e; }","preventionTips":["Always pass --keyword explicitly and quote shell values.","Trim and check emptiness of the term in wrappers before invoking.","Use the correct kwarg name (`keyword`), not query/q.","Fail fast in scripts when the upstream term variable is empty."],"tags":["argument-validation","missing-argument","dianping","cli"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}