{"record":{"id":"9eff354606176986","repo":"jackwener/OpenCLI","slug":"trip-com-tour-search-did-not-return-results-state","errorCode":null,"errorMessage":"Trip.com tour search did not return results (state=${String(result.status)})","messagePattern":"Trip\\.com tour search did not return results \\(state=(.+?)\\)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/trip/tour.js","lineNumber":65,"sourceCode":"    func: async (page, kwargs) => {\n        const query = parseKeyword('query', kwargs.query);\n        const tourType = parseTourType(kwargs.type);\n        const limit = parseListLimit(kwargs.limit);\n\n        const searchUrl = buildTourSearchUrl(query, tourType);\n        await page.goto(searchUrl);\n        const result = await page.evaluate(buildTourSearchJs(query));\n        if (!result || typeof result !== 'object') {\n            throw new CommandExecutionError('Trip.com tour search returned malformed data');\n        }\n        if (result.status === 'captcha') {\n            throw new AuthRequiredError('trip.com', 'Trip.com is asking for a verification; complete it in your browser session and retry');\n        }\n        if (result.status === 'empty') {\n            throw new EmptyResultError('trip tour', `No ${kwargs.type || 'private'} tours for \"${query}\"`);\n        }\n        if (result.status !== 'content') {\n            throw new CommandExecutionError(`Trip.com tour search did not return results (state=${String(result.status)})`);\n        }\n        // Products captured but none carry a name is drift (schema moved), not an empty search;\n        // a genuine no-match resolves as status 'empty' above off the page's \"0 routes found\".\n        const rows = Array.isArray(result.rows) ? result.rows.filter((r) => r.name) : [];\n        if (rows.length === 0) {\n            throw new CommandExecutionError('Trip.com tour search captured products but none carried a name (the product markup may have changed)');\n        }\n        return rows.slice(0, limit).map((r, i) => ({\n            rank: i + 1,\n            name: r.name,\n            type: r.type,\n            rating: r.rating,\n            reviews: r.reviews,\n            price: r.price,\n            currency: 'USD',\n            url: r.url,\n        }));\n    },","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/tour.js#L47-L83","documentation":"This CommandExecutionError is thrown when the tour search page finished loading but its reported state is neither 'captcha', 'empty', nor 'content' — i.e. the page landed in some unexpected state. The library can't classify it, so it surfaces the raw state value for diagnosis.","triggerScenarios":"WAIT-style extraction reporting an unknown status string — e.g. 'timeout', 'redirect', 'error', or a new state introduced by a Trip.com page change; page partially rendered when the script sampled its state.","commonSituations":"Network slowness leaving the page in an intermediate state; Trip.com A/B tests introducing new page states; regional redirects to consent/landing pages.","solutions":["Retry — intermediate render states often resolve with a fresh attempt.","Read the state= value in the message and add handling for it in buildTourSearchJs / the status dispatch.","Increase waits/timeouts before evaluating so the page settles into a known state.","Open searchUrl manually to see what state the page actually ends in."],"exampleFix":"// before\nthrow new CommandExecutionError(`... state=${String(result.status)}`); // unknown state not handled\n// after\nif (result.status === 'loading') { await page.waitForTimeout(3000); result = await page.evaluate(buildTourSearchJs(query)); }","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isClassifiedResult(r) { return r != null && typeof r === 'object' && ['content','empty','captcha'].includes(r.status); }","tryCatchPattern":"try {\n  const rows = await tourSearch(query, type);\n} catch (e) {\n  const m = /state=(\\w+)/.exec(e.message);\n  if (m) { log.warn(`unknown page state ${m[1]}; retrying`); return tourSearch(query, type); }\n  throw e;\n}","preventionTips":["Wait for the page to fully settle before sampling its state.","Handle new states as Trip.com A/B tests introduce them; log unknown state values.","Retry once on unclassified states before surfacing to the user.","Manually inspect searchUrl when a specific state value recurs."],"tags":["scraping","unexpected-state","trip-com"],"backgroundTag":"unexpected-page-state","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}