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

  1. Inspect the raw response body (log response.text() in a local copy) to see what was actually returned
  2. Retry later — often a transient anti-bot or CDN issue
  3. Check if Ctrip changed the endpoint response format
  4. 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

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.

Related errors


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