jackwener/OpenCLI · error · ArgumentError
city unknown city '${cityArg}'. pass a Guazi city code or on
Error message
city unknown city '${cityArg}'. pass a Guazi city code or one of: ${names} What it means
resolveCityCode maps a user-supplied city argument to a Guazi city code. It accepts known city names/codes from CITY_CODE or any 2-3 letter lowercase code (assumed to already be a code); anything else throws this ArgumentError listing the valid name keys. Default when empty is 'bj' (Beijing).
Source
Thrown at clis/guazi/utils.js:66
zhengzhou: 'zz', '郑州': 'zz',
changsha: 'cs', '长沙': 'cs',
qingdao: 'qd', '青岛': 'qd',
shenyang: 'sy', '沈阳': 'sy',
dalian: 'dl', '大连': 'dl',
jinan: 'jn', '济南': 'jn',
hefei: 'hf', '合肥': 'hf',
foshan: 'fs', '佛山': 'fs',
};
/** Resolve a city arg (name or code) to a Guazi city code; defaults to bj. */
export function resolveCityCode(cityArg) {
if (cityArg == null || cityArg === '') return 'bj';
const raw = String(cityArg).trim().toLowerCase();
if (CITY_CODE[raw]) return CITY_CODE[raw];
if (CITY_CODE[String(cityArg).trim()]) return CITY_CODE[String(cityArg).trim()];
if (/^[a-z]{2,3}$/.test(raw)) return raw; // already a code
const names = Object.keys(CITY_CODE).filter((k) => /^[a-z]+$/.test(k)).join(', ');
throw new ArgumentError('city', `unknown city '${cityArg}'. pass a Guazi city code or one of: ${names}`);
}
/** Normalize a clue id: a bare number or a /car-detail/c<id>.htm(l) URL. */
export function normalizeClueId(rawInput) {
const raw = String(rawInput || '').trim();
if (!raw) throw new ArgumentError('clue_id must be a non-empty value');
const m = raw.match(/car-detail\/c(\d+)/) || raw.match(/^c?(\d+)$/);
if (!m) {
throw new ArgumentError(`'${rawInput}' does not look like a guazi clue id (a number, or a /car-detail/c<id>.html URL)`);
}
return m[1];
}
export function requireLimit(value, def, max) {
const raw = value == null || value === '' ? def : value;
const n = typeof raw === 'number' ? raw : Number(String(raw).trim());
if (!Number.isInteger(n) || n < 1 || n > max) {
throw new ArgumentError(`limit must be an integer between 1 and ${max}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a valid code from the listed names (e.g. bj, sh) or a 2-3 letter lowercase code.
- Look at the error message's list of accepted names and pick one exactly.
- Add the missing city mapping to CITY_CODE in clis/guazi/utils.js if your city is legitimately missing.
- Normalize your input (trim, lowercase) before passing it — e.g. ' BJ ' works because of trim/lowercase, 'BJ ' as-is also handled, but 'beijing ' variants may not be in the table.
Example fix
// before guazi browse --city "上海" // after guazi browse --city sh
Defensive patterns
Strategy: validation
Validate before calling
const VALID = new Set(Object.keys(CITY_CODE));
function isValidCityArg(v) {
if (v == null || v === '') return true; // defaults to bj
const raw = String(v).trim().toLowerCase();
return VALID.has(raw) || /^[a-z]{2,3}$/.test(raw);
} Type guard
function isCityCode(v) {
return typeof v === 'string' && /^[a-z]{2,3}$/.test(v.trim().toLowerCase());
} Try / catch
try {
const code = resolveCityCode(cityArg);
} catch (e) {
if (/unknown city/.test(e.message)) {
console.error(e.message);
process.exitCode = 2;
} else throw e;
} Prevention
- Use pinyin codes (bj, sh) from the error's accepted list
- Normalize to lowercase and trim before passing
- Extend CITY_CODE when a needed city is missing
- Avoid passing Chinese characters or full English names
When it happens
Trigger: Calling any guazi command with --city 'beijing' spelled as an unknown full name not in CITY_CODE, e.g. --city "上海" (Chinese characters), --city 'Beijing China', or a 4+ letter word like 'guangz'.
Common situations: Passing a Chinese city name when the table only has pinyin keys; passing a full English name ('shanghai' works but 'shanghais' does not); passing a numeric postal code; typos in the pinyin code.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- <train-no> "${trainNo}" does not look like a 12306 internal
- --from station must not be empty
- --to station must not be empty
- --seat-types must contain only 12306 seat letters/digits (A-
- --from and --to must differ; both resolved to ${fromStation.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/263b47bcc439f7a1.
Report an issue: GitHub.