{"record":{"id":"8ad0f4d186975b62","repo":"jackwener/OpenCLI","slug":"clue-id-must-be-a-non-empty-value","errorCode":null,"errorMessage":"clue_id must be a non-empty value","messagePattern":"clue_id must be a non-empty value","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/guazi/utils.js","lineNumber":72,"sourceCode":"    hefei: 'hf', '合肥': 'hf',\n    foshan: 'fs', '佛山': 'fs',\n};\n\n/** Resolve a city arg (name or code) to a Guazi city code; defaults to bj. */\nexport function resolveCityCode(cityArg) {\n    if (cityArg == null || cityArg === '') return 'bj';\n    const raw = String(cityArg).trim().toLowerCase();\n    if (CITY_CODE[raw]) return CITY_CODE[raw];\n    if (CITY_CODE[String(cityArg).trim()]) return CITY_CODE[String(cityArg).trim()];\n    if (/^[a-z]{2,3}$/.test(raw)) return raw; // already a code\n    const names = Object.keys(CITY_CODE).filter((k) => /^[a-z]+$/.test(k)).join(', ');\n    throw new ArgumentError('city', `unknown city '${cityArg}'. pass a Guazi city code or one of: ${names}`);\n}\n\n/** Normalize a clue id: a bare number or a /car-detail/c<id>.htm(l) URL. */\nexport function normalizeClueId(rawInput) {\n    const raw = String(rawInput || '').trim();\n    if (!raw) throw new ArgumentError('clue_id must be a non-empty value');\n    const m = raw.match(/car-detail\\/c(\\d+)/) || raw.match(/^c?(\\d+)$/);\n    if (!m) {\n        throw new ArgumentError(`'${rawInput}' does not look like a guazi clue id (a number, or a /car-detail/c<id>.html URL)`);\n    }\n    return m[1];\n}\n\nexport function requireLimit(value, def, max) {\n    const raw = value == null || value === '' ? def : value;\n    const n = typeof raw === 'number' ? raw : Number(String(raw).trim());\n    if (!Number.isInteger(n) || n < 1 || n > max) {\n        throw new ArgumentError(`limit must be an integer between 1 and ${max}`);\n    }\n    return n;\n}\n\nexport function clean(s) {\n    return String(s == null ? '' : s).replace(/\\s+/g, ' ').trim();","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/guazi/utils.js#L54-L90","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Provide a numeric clue id, e.g. guazi car --clue_id 100200300.","If you have a detail URL, pass the whole URL (/car-detail/c<id>.html) — it is accepted.","Check that the shell variable or upstream field actually contains a value before invoking.","Get a fresh id from 'guazi browse' output."],"exampleFix":"// before\nCLUE_ID=\"\"\nguazi car --clue_id \"$CLUE_ID\"\n// after\nCLUE_ID=100200300\nguazi car --clue_id \"$CLUE_ID\"","handlingStrategy":"validation","validationCode":"if (clueId == null || String(clueId).trim() === '') {\n  throw new Error('clue_id is required (a numeric id or /car-detail/c<id>.html URL)');\n}","typeGuard":"function hasClueId(v) {\n  return v != null && String(v).trim() !== '';\n}","tryCatchPattern":"try {\n  const car = await guaziCar({ clue_id: id });\n} catch (e) {\n  if (/clue_id must be a non-empty/.test(e.message)) {\n    console.error('Provide a clue id, e.g. guazi car --clue_id 100200300');\n  } else throw e;\n}","preventionTips":["Check upstream variables are set before invoking (${VAR:-} guards in shell)","Fail fast with your own empty-check in scripts","Fetch fresh ids from 'guazi browse' when missing","Validate pipeline inputs at each step"],"tags":["argument-validation","cli","missing-value"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}