jackwener/OpenCLI · error · CommandExecutionError
Ctrip flight API failed (status=${String(payload?.status)}):
Error message
Ctrip flight API failed (status=${String(payload?.status)}): ${cleanString(payload?.msg) || 'unknown error'} What it means
This error is thrown by parseBatchSearchCaptures when the captured Ctrip batchSearch HTTP response body parses to JSON whose top-level `status` field is not 0. Ctrip's API signals business-level success with status===0; any other value (with an optional human-readable `msg`) means the upstream search request was rejected or failed. The library surfaces the upstream status code and message verbatim so the developer can see what Ctrip complained about.
Source
Thrown at clis/ctrip/flight.js:88
}
if (status !== 200) {
throw new CommandExecutionError(`Ctrip flight API returned HTTP ${status || 'unknown'}`);
}
if (entry?.responseBodyTruncated === true) {
throw new CommandExecutionError('Ctrip flight API response exceeded the browser capture limit');
}
if (typeof entry?.responsePreview !== 'string') {
throw new CommandExecutionError('Ctrip flight API response body was unavailable');
}
let payload;
try {
payload = JSON.parse(entry.responsePreview);
}
catch {
throw new CommandExecutionError('Ctrip flight API returned invalid JSON');
}
if (payload?.status !== 0) {
throw new CommandExecutionError(`Ctrip flight API failed (status=${String(payload?.status)}): ${cleanString(payload?.msg) || 'unknown error'}`);
}
const itineraries = payload?.data?.flightItineraryList;
if (!Array.isArray(itineraries) || typeof payload?.data?.context?.finished !== 'boolean') {
throw new CommandExecutionError('Ctrip flight API returned a malformed batchSearch payload');
}
for (const itinerary of itineraries) {
const id = cleanString(itinerary?.itineraryId);
if (!id) throw new CommandExecutionError('Ctrip flight API returned an itinerary without an id');
byId.set(id, itinerary);
}
finished = payload.data.context.finished;
}
if (!finished) {
throw new CommandExecutionError('Ctrip flight batchSearch ended before the upstream search reported completion');
}
return [...byId.values()];
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Read the upstream `msg` in the error message — it names the concrete Ctrip business failure and usually dictates the fix.
- Retry the search in a fresh browser session / clear cookies so Ctrip issues a new session and token.
- Re-run interactively in a real browser first; if a captcha or verification appears, complete it, then retry the command.
- If msg indicates invalid parameters, adjust route/date arguments (valid IATA codes, ISO dates, present/future dates).
- If it persists, check whether Ctrip changed the batchSearch API contract and update the capture pattern/parsing in clis/ctrip/flight.js.
Example fix
// before (stale session retrying blindly)
const rows = await cli.run(['ctrip', 'flight', 'PEK', 'SHA', date]);
// after (fresh session / verify manually on persistent failure)
try {
const rows = await cli.run(['ctrip', 'flight', 'PEK', 'SHA', date]);
} catch (err) {
if (String(err.message).includes('Ctrip flight API failed')) {
await browser.newProfileContext(); // drop cookies, get a fresh Ctrip session
const rows = await cli.run(['ctrip', 'flight', 'PEK', 'SHA', date]);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// cannot be pre-validated client-side; verify inputs are well-formed first
if (!parseIataCode(from) || !parseIataCode(to) || !parseIsoDate(date)) {
throw new Error('invalid route/date arguments; fix before invoking the flight search');
} Type guard
function isBatchSearchOk(payload) {
return !!payload && typeof payload === 'object' && payload.status === 0;
} Try / catch
try {
const rows = await cli.run(['ctrip', 'flight', from, to, date]);
} catch (err) {
const m = String(err.message).match(/Ctrip flight API failed \(status=(\S+)\): (.*)/);
if (m) console.error(`Ctrip business error ${m[1]}: ${m[2]} — refresh session and retry`);
else throw err;
} Prevention
- Use a fresh, logged-in browser profile so the Ctrip session and tokens are valid
- Complete any captcha/verification manually before automating
- Validate route (IATA) and date arguments before running the search
- Throttle request frequency to avoid Ctrip risk control
- Log the full upstream msg from the error for diagnosis
When it happens
Trigger: The browser-captured POST to /international/search/api/search/batchSearch returns HTTP 200 but payload.status !== 0 — e.g. expired/invalid Ctrip session cookies, risk-control rejection, invalid search parameters forwarded by the page, or Ctrip-side throttling/business errors.
Common situations: Developers hit this when reusing a stale browser profile whose Ctrip session expired, when Ctrip's anti-bot risk control flags the automated browser, when querying routes/dates Ctrip considers invalid, or during Ctrip API contract changes that shift the status field semantics.
Related errors
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- arXiv API HTTP ${resp.status}
- 获取视频分P信息失败: ${error?.message || error}
- 获取视频信息失败: ${err?.message || err}
- 获取视频播放信息失败: ${err?.message || err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4bc04c60baf97ae7.
Report an issue: GitHub.