{"record":{"id":"2e7ccfe075cbc2f5","repo":"jackwener/OpenCLI","slug":"ctrip-flight-network-capture-returned-malformed-en","errorCode":null,"errorMessage":"Ctrip flight network capture returned malformed entries","messagePattern":"Ctrip flight network capture returned malformed entries","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/ctrip/flight.js","lineNumber":59,"sourceCode":"\nfunction cleanString(value) {\n    return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction timePart(value) {\n    const match = cleanString(value).match(/(?:^|\\s)([0-2]\\d:[0-5]\\d)(?::[0-5]\\d)?$/);\n    return match?.[1] || '';\n}\n\nfunction cabinLabel(value) {\n    const labels = { Y: '经济舱', S: '超级经济舱', C: '公务舱', F: '头等舱' };\n    const codes = [...new Set(cleanString(value).toUpperCase().match(/[YSCF]/g) || [])];\n    return codes.length > 0 ? codes.map((code) => labels[code]).join('/') : (cleanString(value) || null);\n}\n\nfunction 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') {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/ctrip/flight.js#L41-L77","documentation":"A CommandExecutionError thrown by parseBatchSearchCaptures in clis/ctrip/flight.js when the entries passed in from the network-capture phase are not an array. The flight CLI listens for Ctrip's batch-search XHR responses (entries matching CAPTURE_PATTERN) and this guard rejects a malformed capture payload before any parsing proceeds.","triggerScenarios":"itineraries calls parseBatchSearchCaptures with a non-array value (null/undefined/object) instead of the expected array of captured network entries — e.g. the browser capture step failed, returned nothing, or the plumbing passed the wrong shape.","commonSituations":"Browser extension/CDP capture layer silently failing so no entries were collected; internal wiring bug between capture and parse; library version drift where the capture API changed shape; page crashed before any batch-search request fired.","solutions":["Retry the command — a transient capture failure often disappears on rerun.","Update the library in case a capture-shape fix has shipped.","Check the browser session is healthy (page loaded, no crash) and rerun in a fresh session.","If reproducible, file an issue with the command and version — this indicates the capture layer, not your input, is broken."],"exampleFix":"// before\nconst result = await cli(['flight', '--from','PEK','--to','SHA','--date',d]);\n// after\ntry { const result = await cli(['flight', ...]); } catch (e) {\n  if (String(e.message).includes('malformed entries')) return await cli(['flight', ...]); // retry once\n  throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isMalformedCaptureError(e) { return e && String(e.message || '').includes('malformed entries'); }","tryCatchPattern":"try { return await runFlightItineraries(args); }\ncatch (e) { if (isMalformedCaptureError(e)) { await sleep(5000); return await runFlightItineraries(args); } throw e; }","preventionTips":["Retry once — capture layers can transiently return nothing.","Ensure the browser session is healthy and the page fully loads before capture.","Pin/update library versions so capture and parse shapes stay in sync.","Escalate persistent occurrences as a capture-layer bug with command, URL, and version."],"tags":["scraping","network-capture","ctrip","parser"],"backgroundTag":"dom-parser-drift","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}