{"record":{"id":"75cff95ebaad8005","repo":"jackwener/OpenCLI","slug":"station-must-not-be-empty","errorCode":null,"errorMessage":"station must not be empty","messagePattern":"station must not be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/12306/utils.js","lineNumber":76,"sourceCode":"            city: parts[7] || '',\n        });\n    }\n    if (stations.length === 0) {\n        throw new CommandExecutionError('Failed to parse 12306 station_name.js: no station records found');\n    }\n    return stations;\n}\n\n/**\n * Resolve a user-supplied station identifier to a telecode.\n *\n * Accepts Chinese name (`上海虹桥`), telecode (`AOH`), pinyin\n * (`shanghaihongqiao`), short alias (`shh`), or city name with a\n * preference for the city's main station.\n */\nexport function resolveStation(stations, input) {\n    const trimmed = String(input ?? '').trim();\n    if (!trimmed) throw new ArgumentError('station must not be empty');\n    if (STATION_CODE_RE.test(trimmed)) {\n        const exact = stations.find((s) => s.code === trimmed);\n        if (exact) return exact;\n        throw new ArgumentError(`Unknown 12306 station telecode \"${trimmed}\"`);\n    }\n    const lower = trimmed.toLowerCase();\n    const exactName = stations.find((s) => s.name === trimmed);\n    if (exactName) return exactName;\n    const exactPinyin = stations.find((s) => s.pinyin === lower);\n    if (exactPinyin) return exactPinyin;\n    const exactAbbr = stations.find((s) => s.abbr === lower || s.short === lower);\n    if (exactAbbr) return exactAbbr;\n    throw new ArgumentError(`Unknown 12306 station \"${trimmed}\"`, 'Try the Chinese name (上海虹桥), the 3-4 letter telecode (AOH), or full pinyin (shanghaihongqiao).');\n}\n\nexport function validateDate(value) {\n    if (!DATE_RE.test(String(value ?? ''))) {\n        throw new ArgumentError(`date must be YYYY-MM-DD, got \"${value}\"`);","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/12306/utils.js#L58-L94","documentation":"ArgumentError from resolveStation when the station input is missing, null, or whitespace-only after trimming. resolveStation is the shared identifier-to-telecode resolver used for both from and to stations; an empty value cannot be matched against the bundle, so it fails fast before the lookup.","triggerScenarios":"Calling resolveStation (directly or via the trains command internals) with undefined/null/'' input — e.g. `resolveStation(stations, '')`, or a caller that already trimmed its argument to empty before delegating.","commonSituations":"Library callers building station lookup utilities and passing an unset variable; splitting user input (e.g. \"北京→上海\" on a wrong delimiter) yielding an empty part; CSV/script rows with a blank station column.","solutions":["Ensure the station string is non-empty before calling: Chinese name, telecode, pinyin, or short alias.","Validate/skip blank rows in batch scripts before resolving.","Fix delimiter-based parsing so both origin and destination parts are captured.","Reuse the command-level ArgumentError message to surface which argument was blank in your wrapper."],"exampleFix":"// before\nconst toStation = resolveStation(stations, parts[1] ?? ''); // parts[1] may be undefined\n// after\nif (!parts[1]?.trim()) throw new Error(`row ${i}: destination station missing`);\nconst toStation = resolveStation(stations, parts[1]);","handlingStrategy":"validation","validationCode":"if (!input || !String(input).trim()) {\n  throw new Error('station identifier required (Chinese name, telecode, pinyin, or alias)');\n}","typeGuard":"function hasStationInput(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  const station = resolveStation(stations, input);\n} catch (e) {\n  if (e.name === 'ArgumentError' && /station must not be empty/.test(e.message)) {\n    console.error('Blank station input — check your delimiter parsing or config values.');\n  } else throw e;\n}","preventionTips":["Check input for emptiness right after parsing user data or config.","When splitting route strings, verify both parts captured a station.","Skip or flag blank rows in batch/CSV processing before resolution.","Centralize station input validation in one helper reused by all callers."],"tags":["argument-validation","empty-input","station-resolution"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}