{"record":{"id":"347ca1cdf02c5550","repo":"jackwener/OpenCLI","slug":"ctrip-flight-api-response-exceeded-the-browser-cap","errorCode":null,"errorMessage":"Ctrip flight API response exceeded the browser capture limit","messagePattern":"Ctrip flight API response exceeded the browser capture limit","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/ctrip/flight.js","lineNumber":75,"sourceCode":"function parseBatchSearchCaptures(entries) {\n    if (!Array.isArray(entries)) {\n        throw new CommandExecutionError('Ctrip flight network capture returned malformed entries');\n    }\n    const captured = entries.filter((entry) => String(entry?.url || '').includes(CAPTURE_PATTERN));\n    if (captured.length === 0) return null;\n\n    const byId = new Map();\n    let finished = false;\n    for (const entry of captured) {\n        const status = Number(entry?.responseStatus || 0);\n        if (status === 401 || status === 403) {\n            throw new AuthRequiredError('flights.ctrip.com', `Ctrip flight API returned HTTP ${status}; complete any verification in the browser and retry`);\n        }\n        if (status !== 200) {\n            throw new CommandExecutionError(`Ctrip flight API returned HTTP ${status || 'unknown'}`);\n        }\n        if (entry?.responseBodyTruncated === true) {\n            throw new CommandExecutionError('Ctrip flight API response exceeded the browser capture limit');\n        }\n        if (typeof entry?.responsePreview !== 'string') {\n            throw new CommandExecutionError('Ctrip flight API response body was unavailable');\n        }\n        let payload;\n        try {\n            payload = JSON.parse(entry.responsePreview);\n        }\n        catch {\n            throw new CommandExecutionError('Ctrip flight API returned invalid JSON');\n        }\n        if (payload?.status !== 0) {\n            throw new CommandExecutionError(`Ctrip flight API failed (status=${String(payload?.status)}): ${cleanString(payload?.msg) || 'unknown error'}`);\n        }\n        const itineraries = payload?.data?.flightItineraryList;\n        if (!Array.isArray(itineraries) || typeof payload?.data?.context?.finished !== 'boolean') {\n            throw new CommandExecutionError('Ctrip flight API returned a malformed batchSearch payload');\n        }","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/flight.js#L57-L93","documentation":"This CommandExecutionError is thrown when the captured batchSearch response body was truncated (responseBodyTruncated === true), i.e. the payload exceeded the browser/CDP capture size limit. The library cannot parse a partial JSON body safely, so it fails fast rather than returning incomplete flight results. It is a capture-infrastructure limitation, not a Ctrip API failure.","triggerScenarios":"A batchSearch response whose JSON body is larger than the CDP response-body capture limit — typically very popular routes with huge itinerary lists, wide multi-passenger searches, or limit set to the maximum (50).","commonSituations":"Searching dense domestic trunk routes (e.g. PEK->SHA) around holidays with limit=50; capture buffer configured too small in the CDP layer; Ctrip returning an unusually large payload (many fare families/bundles).","solutions":["Re-run with a smaller --limit (e.g. 20 or fewer) so the response payload stays under the capture limit.","Narrow the search (specific cabin/airline via the page UI or the round-trip command) to reduce result size.","Increase the browser capture/CDP response-body limit in the host tooling if you control it.","If truncation persists, split the query into smaller time windows or routes."],"exampleFix":"// before\nawait cli.itineraries({ from: 'PEK', to: 'SHA', date: '2026-10-01', limit: 50 });\n// after: keep payload under capture limit\nawait cli.itineraries({ from: 'PEK', to: 'SHA', date: '2026-10-01', limit: 20 });","handlingStrategy":"validation","validationCode":"// check requested size before invoking\nif (Number(args.limit) > 20) {\n  console.warn('Large limits can exceed the browser capture limit; prefer limit <= 20 on dense routes.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await cli.itineraries({ ...args, limit: 20 });\n} catch (err) {\n  if (/capture limit/i.test(err.message || '')) {\n    return cli.itineraries({ ...args, limit: Math.max(1, Math.floor((args.limit || 20) / 2)) });\n  }\n  throw err;\n}","preventionTips":["Keep --limit modest (<=20) on busy trunk routes and holiday dates.","Narrow searches (specific dates/routes) to shrink payloads.","If you control the tooling, raise the CDP response-body size limit.","Treat this error as 'query too big' and automatically halve the limit on retry."],"tags":["payload-size","truncation","cdp","browser-capture"],"backgroundTag":"response-body-truncated","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}