jackwener/OpenCLI · error · ArgumentError
--${name} is not a valid place name: ${JSON.stringify(raw)}
Error message
--${name} is not a valid place name: ${JSON.stringify(raw)} What it means
After the presence check, parsePlaceName rejects values longer than 20 characters or containing ASCII control characters (\x00-\x1f, including newlines and tabs), since the list queries pass the raw Chinese place name into URLs. The rejected input is echoed JSON-escaped in the ArgumentError message.
Source
Thrown at clis/ctrip/utils.js:524
})()
`;
}
/** Validate a 1-50 result limit shared by the browser-mode list commands (default 20). */
export function parseListLimit(raw, fallback = 20) {
return parseStrictIntegerRange('limit', raw, fallback);
}
/** Validate a Chinese place keyword (station, city, port, or destination) for the browser list queries. */
export function parsePlaceName(name, raw) {
if (raw === undefined || raw === null || String(raw).trim() === '') {
throw new ArgumentError(`--${name} is required (e.g. 北京 / 上海)`);
}
const value = String(raw).trim();
// These list pages key on the raw Chinese place name; reject control
// characters and over-long input rather than passing them through.
if (value.length > 20 || /[\x00-\x1f]/.test(value)) {
throw new ArgumentError(`--${name} is not a valid place name: ${JSON.stringify(raw)}`);
}
return value;
}
export function buildTrainListUrl(fromName, toName, date) {
const params = new URLSearchParams({
dStationName: fromName,
aStationName: toName,
dDate: date,
ticketType: '1',
});
return `https://trains.ctrip.com/webapp/train/list?${params.toString()}`;
}
/**
* Browser-context IIFE that extracts train rows from the trains.ctrip.com
* list page. Each `.card-white.list-item` exposes stable, class-keyed leaf
* fields (`.from/.mid/.to/.rbox/.surplus-list`), so we read by selector ratherView on GitHub (pinned to 49907e53dc)
Solutions
- Shorten the value to the bare Chinese place name (<= 20 chars).
- Strip newlines/tabs/control characters: value.replace(/[\x00-\x1f]/g, '').trim().
- Fix scripts that interpolate untrimmed command output into the flag.
Example fix
// before ctrip trains --from-city "上海市浦东新区世纪大道1000号" // after ctrip trains --from-city 上海
Defensive patterns
Strategy: validation
Validate before calling
const name = String(raw).trim();
if (name.length > 20 || /[\x00-\x1f]/.test(name)) {
throw new Error('place name must be <=20 chars with no control characters: ' + JSON.stringify(raw));
} Type guard
const isValidPlaceName = (v) => typeof v === 'string' && v.trim().length >= 1 && v.trim().length <= 20 && !/[\x00-\x1f]/.test(v.trim());
Try / catch
try {
const name = parsePlaceName('to-city', raw);
} catch (e) {
if (e instanceof ArgumentError && e.message.includes('not a valid place name')) {
const cleaned = String(raw).replace(/[\x00-\x1f]/g, '').trim().slice(0, 20);
return parsePlaceName('to-city', cleaned);
}
throw e;
} Prevention
- Sanitize pasted input: strip control chars and trim newlines from command substitution.
- Pass bare place keywords, not full addresses.
- Cap input length at 20 characters in wrappers/forms.
When it happens
Trigger: Passing --from-city/--to-city/--port/--destination values that exceed 20 chars or embed control characters: multi-line paste, tab/newline inside the name, strings with stray escapes, or overly long descriptions instead of a place keyword.
Common situations: Copy-pasting a whole address or sentence from notes into the flag, pasting names with trailing newline from terminal output (e.g. $(...)), or script bugs that join multiple values with '\n'.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/74fc6a7dd10300a8.
Report an issue: GitHub.