{"record":{"id":"e460259339d15fe5","repo":"jackwener/OpenCLI","slug":"unknown-city-cityarg-pass-a-numeric-cityid","errorCode":null,"errorMessage":"unknown city '${cityArg}'. pass a numeric cityId, a pinyin slug (e.g. shantou), a Chinese name listed on dianping.com/citylist, or one of: ${known}","messagePattern":"unknown city '(.+?)'\\. pass a numeric cityId, a pinyin slug \\(e\\.g\\. shantou\\), a Chinese name listed on dianping\\.com/citylist, or one of: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/dianping/cityResolver.js","lineNumber":76,"sourceCode":"    // back to dynamic resolution rather than surface the error to the user.\n    try {\n        const staticId = resolveCityId(raw);\n        if (staticId != null) return staticId;\n    } catch (err) {\n        if (err?.code !== 'ARGUMENT') throw err;\n    }\n\n    if (RESOLVE_CACHE.has(lowered)) return RESOLVE_CACHE.get(lowered);\n    if (RESOLVE_CACHE.has(raw)) return RESOLVE_CACHE.get(raw);\n\n    let pinyin = null;\n    if (PINYIN_RE.test(lowered)) {\n        pinyin = lowered;\n    } else if (CHINESE_RE.test(raw)) {\n        pinyin = await lookupPinyinFromCitylist(page, raw);\n        if (!pinyin) {\n            const known = Object.keys(CITY_ID).filter((k) => /^[a-z]+$/.test(k)).join(', ');\n            throw new ArgumentError(\n                'city',\n                `unknown city '${cityArg}'. pass a numeric cityId, a pinyin slug (e.g. shantou), `\n                + `a Chinese name listed on dianping.com/citylist, or one of: ${known}`,\n            );\n        }\n    } else {\n        const known = Object.keys(CITY_ID).filter((k) => /^[a-z]+$/.test(k)).join(', ');\n        throw new ArgumentError(\n            'city',\n            `unknown city '${cityArg}'. pass a numeric cityId, a pinyin slug (e.g. shantou), `\n            + `a Chinese name listed on dianping.com/citylist, or one of: ${known}`,\n        );\n    }\n\n    const cityId = await fetchCityIdByPinyin(page, pinyin);\n    if (!cityId) {\n        throw new CommandExecutionError(\n            `dianping could not resolve cityId for '${cityArg}' (pinyin=${pinyin}); `","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dianping/cityResolver.js#L58-L94","documentation":"ArgumentError from resolveCityIdAsync when the --city argument is a Chinese city name that is not found in the static CITY_ID map and lookupPinyinFromCitylist could not map it either (no pinyin derived). The library needs a numeric cityId or pinyin slug to build Dianping search URLs. Thrown because the Chinese name could not be translated to a pinyin slug.","triggerScenarios":"Passing city='重庆' (or any Chinese name) where CHINESE_RE matches but lookupPinyinFromCitylist returns no pinyin — either the name is absent from dianping.com/citylist or the citylist scrape failed, and the name is not a key of the static CITY_ID map.","commonSituations":"Typo or alternate/old name for a Chinese city (e.g.使用简称 or 旧称); citylist page failed to render so the online lookup couldn't run; using a district name not listed as a top-level city.","solutions":["Pass the numeric cityId directly if you know it (e.g. city=108) — skips name resolution entirely.","Use the pinyin slug form instead of Chinese characters, e.g. city='chongqing'.","Check the error's known list (lowercase CITY_ID keys) and use one of the supported slugs.","If the Chinese name should work, verify dianping.com/citylist renders (may have failed — see the citylist-empty error) and that the name matches exactly what the site lists."],"exampleFix":"// before\nawait cli.dianping.search({ keyword: '火锅', city: '重庆' });\n// after\nawait cli.dianping.search({ keyword: '火锅', city: 'chongqing' }); // or a numeric cityId","handlingStrategy":"validation","validationCode":"function resolveCityArg(city) {\n  if (/^\\d+$/.test(city)) return city;\n  if (/^[a-z]+$/.test(city)) return city; // pinyin slug\n  throw new Error(`pass a numeric cityId or pinyin slug, not '${city}'`);\n}","typeGuard":"function isKnownCity(city, map) { return typeof city === 'string' && ( /^\\d+$/.test(city) || /^[a-z]+$/.test(city) || city in map ); }","tryCatchPattern":"try { await cli.dianping.search({ keyword, city }); }\ncatch (e) { if (e.name === 'ArgumentError' && e.field === 'city') { console.error('use cityId or pinyin slug, e.g. shantou'); process.exitCode = 2; } else throw e; }","preventionTips":["Prefer pinyin slugs or numeric cityIds over Chinese names.","Validate city input format in your wrapper before invoking the CLI.","Keep a local city-name → cityId mapping for your common cities.","Handle the printed `known` slug list as the source of truth for supported cities."],"tags":["argument-validation","dianping","city-resolution","pinyin"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}