{"record":{"id":"ab8177b855c23d0b","repo":"jackwener/OpenCLI","slug":"trip-com-package-search-failed-with-status-respo","errorCode":null,"errorMessage":"Trip.com package search failed with status ${response.status}","messagePattern":"Trip\\.com package search failed with status (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/trip/utils.js","lineNumber":958,"sourceCode":"        flightcriteria: {\n            osource: 1, triptype: 1, fmap: 19, sflag: 0, rtype: 2,\n            seglist: [{ segno: 1, ddate: depart, sgrade: 4, dcode, acode }],\n            pinfo: { adults, children: 0, babys: 0 },\n        },\n        hotelcriteria: { chin: depart, chout: ret, hcityid, rnum: 1 },\n    };\n    let response;\n    try {\n        response = await fetch(PACKAGE_SEARCH_ENDPOINT, {\n            method: 'POST',\n            headers: { 'content-type': 'application/json', currency: 'USD' },\n            body: JSON.stringify(body),\n        });\n    } catch (err) {\n        throw new CommandExecutionError(`Trip.com package search fetch failed: ${err instanceof Error ? err.message : String(err)}`);\n    }\n    if (!response.ok) {\n        throw new CommandExecutionError(`Trip.com package search failed with status ${response.status}`);\n    }\n    let payload;\n    try {\n        payload = await response.json();\n    } catch (err) {\n        throw new CommandExecutionError(`Trip.com package search returned invalid JSON: ${err instanceof Error ? err.message : String(err)}`);\n    }\n    if (!Array.isArray(payload?.grouplist)) {\n        throw new CommandExecutionError('Trip.com package search returned malformed payload: missing grouplist array');\n    }\n    return payload.grouplist;\n}\n\n/**\n * Project a package flight group into the stable adapter column shape. A group's\n * `flightlist` is the itinerary legs (one for a nonstop), so the route summary\n * reads the departure off the first leg and the arrival off the last, with the\n * leg count minus one as the stop count. `price` is the per-person package","sourceCodeStart":940,"sourceCodeEnd":976,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/utils.js#L940-L976","documentation":"fetchPackageSearch checks response.ok after the POST resolves; a non-2xx HTTP status (403, 429, 500, 502, 503, etc.) is thrown as CommandExecutionError with 'Trip.com package search failed with status N'. The network call succeeded but Trip.com's server rejected or failed the request.","triggerScenarios":"Posting package search requests too rapidly (429); Trip.com WAF blocking the request (403); wrong endpoint or params causing 404/400; Trip.com server errors (5xx) during outage windows; missing/invalid headers (currency, content-type) triggering rejection.","commonSituations":"Batch scripts issuing many package searches without throttling; expired anti-bot/session state; API path or payload schema drift after a Trip.com update; regional outages or maintenance.","solutions":["Capture the status code and, if possible, the response body to identify the cause","Add throttling/delay between package search calls to avoid 429","Implement retry with exponential backoff for 5xx and 429 responses","Validate the POST body/headers match the current API contract; update the client if Trip.com changed it"],"exampleFix":"// before\nawait Promise.all(cities.map(c => search(c))) // bursts -> 429\n// after\nfor (const c of cities) { await search(c); await sleep(2000) }","handlingStrategy":"retry","validationCode":"// sanity-check required params before POSTing\nif (!fromCity || !toCity || !departDate) throw new Error('from, to and departDate are required for package search');","typeGuard":"null","tryCatchPattern":"async function packagesWithRetry(params, retries = 3) {\n  for (let i = 0; i < retries; i++) {\n    try { return await searchPackages(params); }\n    catch (e) {\n      const m = /failed with status (\\d+)/.exec(e.message);\n      if (m && (m[1] === '429' || m[1].startsWith('5')) && i < retries - 1) { await sleep(1500 * 2 ** i); continue; }\n      throw e;\n    }\n  }\n}","preventionTips":["Space out package search calls to stay under rate limits","Retry only 429/5xx; surface 4xx immediately for parameter fixes","Keep the request body/headers aligned with the current Trip.com contract","Alert on repeated 403 — usually anti-bot/WAF blocking"],"tags":["http","api","status-code","rate-limit"],"backgroundTag":"http-non-ok-status","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}