jackwener/OpenCLI · error · ArgumentError

clue_id must be a non-empty value

Error message

clue_id must be a non-empty value

What it means

normalizeClueId requires a non-empty clue id (a bare number or a /car-detail/c<id>.html URL). When the input is null, undefined, empty string, or whitespace-only, it throws this short ArgumentError because a clue id is mandatory to build the car-detail URL.

Source

Thrown at clis/guazi/utils.js:72

    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}`);
    }
    return n;
}

export function clean(s) {
    return String(s == null ? '' : s).replace(/\s+/g, ' ').trim();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Provide a numeric clue id, e.g. guazi car --clue_id 100200300.
  2. If you have a detail URL, pass the whole URL (/car-detail/c<id>.html) — it is accepted.
  3. Check that the shell variable or upstream field actually contains a value before invoking.
  4. Get a fresh id from 'guazi browse' output.

Example fix

// before
CLUE_ID=""
guazi car --clue_id "$CLUE_ID"
// after
CLUE_ID=100200300
guazi car --clue_id "$CLUE_ID"
Defensive patterns

Strategy: validation

Validate before calling

if (clueId == null || String(clueId).trim() === '') {
  throw new Error('clue_id is required (a numeric id or /car-detail/c<id>.html URL)');
}

Type guard

function hasClueId(v) {
  return v != null && String(v).trim() !== '';
}

Try / catch

try {
  const car = await guaziCar({ clue_id: id });
} catch (e) {
  if (/clue_id must be a non-empty/.test(e.message)) {
    console.error('Provide a clue id, e.g. guazi car --clue_id 100200300');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling 'guazi car --clue_id ""' or omitting the argument so undefined/null flows in; piping an empty variable like CLUE_ID= into the command; a prior command returning an empty field that is passed through.

Common situations: Shell variable not set (clue_id="$CLUE_ID" with CLUE_ID unset); JSON output parsing extracting a missing field; copying only the 'c' prefix without the number into a pipeline that then trims to empty.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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