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

  1. Pass a valid code from the listed names (e.g. bj, sh) or a 2-3 letter lowercase code.
  2. Look at the error message's list of accepted names and pick one exactly.
  3. Add the missing city mapping to CITY_CODE in clis/guazi/utils.js if your city is legitimately missing.
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/263b47bcc439f7a1. Report an issue: GitHub.