jackwener/OpenCLI · error · CliError
COMMAND_EXEC
COMMAND_EXEC
Error message
ctrip suggest returned invalid JSON: ${err instanceof Error ? err.message : String(err)} What it means
fetchSuggest calls response.json() and wraps parse failures in a COMMAND_EXEC CliError. This fires when the HTTP response body is not valid JSON — typically an HTML error page, a captcha/anti-bot interstitial, or an empty body returned with a 200 status.
Source
Thrown at clis/ctrip/utils.js:89
} catch (err) {
throw new CliError(
'FETCH_ERROR',
`ctrip suggest fetch failed: ${err instanceof Error ? err.message : String(err)}`,
'Check your network connection and retry',
);
}
if (!response.ok) {
throw new CliError(
'FETCH_ERROR',
`ctrip suggest failed with status ${response.status}`,
'Retry the command or verify ctrip.com is reachable',
);
}
let payload;
try {
payload = await response.json();
} catch (err) {
throw new CliError(
'COMMAND_EXEC',
`ctrip suggest returned invalid JSON: ${err instanceof Error ? err.message : String(err)}`,
'Ctrip may have changed the endpoint response format; retry later',
);
}
if (payload && payload.Result === false) {
const code = payload.ErrorCode ?? 'unknown';
throw new CliError(
'COMMAND_EXEC',
`ctrip suggest API returned Result=false (ErrorCode=${code})`,
'Verify keyword and retry; this typically means upstream rejected the query envelope',
);
}
if (!payload || typeof payload !== 'object' || !payload.Response || typeof payload.Response !== 'object' || !Array.isArray(payload.Response.searchResults)) {
throw new CliError(
'COMMAND_EXEC',
'ctrip suggest returned malformed response shape: Response.searchResults is missing or not an array',
'Ctrip may have changed the endpoint response format; retry later',View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw response body (log response.text() in a local copy) to see what was actually returned
- Retry later — often a transient anti-bot or CDN issue
- Check if Ctrip changed the endpoint response format
- Slow down request rate to avoid triggering anti-bot pages
Defensive patterns
Strategy: try-catch
Try / catch
try {
const rows = await fetchSuggest(keyword, 'D');
} catch (err) {
if (err.code === 'COMMAND_EXEC' && /invalid JSON/.test(err.message)) {
// capture raw body via a debug fetch to diagnose (captcha page? HTML error?)
}
throw err;
} Prevention
- Log response bodies when debugging to spot HTML anti-bot pages
- Reduce request frequency to avoid triggering challenges
- Retry later on transient CDN/anti-bot issues
- Pin and review parsing code when Ctrip changes formats
When it happens
Trigger: fetchSuggest(query, searchType) gets a 200 response whose body fails JSON.parse — e.g. Ctrip returned an HTML block page, a login wall, or truncated/garbled content.
Common situations: Anti-bot gateway serves an HTML challenge with status 200; CDN error page; response interrupted mid-transfer; Ctrip A/B testing a new response format.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- hf spaces returned malformed JSON: ${err?.message ?? err}
- ${label} returned invalid JSON: ${outcome.detail}
- ${label} returned malformed JSON: ${err?.message ?? err}
- ${label} returned a non-JSON response
- archive search returned malformed JSON: ${error?.message ||
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/68f40e8d5888d57b.
Report an issue: GitHub.