{"record":{"id":"0d7316d3a997344e","repo":"jackwener/OpenCLI","slug":"no-kwargs-type-private-tours-for-query","errorCode":null,"errorMessage":"No ${kwargs.type || 'private'} tours for \"${query}\"","messagePattern":"No (.+?) tours for \"(.+?)\"","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"info","filePath":"clis/trip/tour.js","lineNumber":62,"sourceCode":"        'price', 'currency',\n        'url',\n    ],\n    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',","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trip/tour.js#L44-L80","documentation":"This EmptyResultError means the tour search page explicitly reported 'no routes found' for the query (result.status === 'empty'), i.e. Trip.com has no matching tours for that destination and tour type. It is a clean no-match signal, deliberately separated from schema-drift and captcha cases.","triggerScenarios":"Calling tour search with a destination that has zero private (or group, per --type) tours on Trip.com, or a misspelled/obscure query that matches no tour products.","commonSituations":"Small towns or attractions Trip.com doesn't sell tours for; using --type=group in a market where only private tours exist; localized transliterations that match nothing.","solutions":["Try the other --type value (group vs private) — availability differs per tab.","Simplify or correct the destination query string.","Search a nearby major city that has tour inventory.","Catch EmptyResultError and treat it as an empty result set in your application."],"exampleFix":"// before\nawait tripTour({ query: 'Hallstatt', type: 'group' }); // no group tours\n// after\ntry {\n  return await tripTour({ query: 'Hallstatt', type: 'private' });\n} catch (e) {\n  if (e.name === 'EmptyResultError') return [];\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// sanity-check the query before spending a page load\nif (!query || query.trim().length < 3) throw new Error('provide a meaningful destination name');","typeGuard":"function isPlausibleDestination(q) { return typeof q === 'string' && q.trim().length >= 3; }","tryCatchPattern":"try {\n  const rows = await tourSearch(query, type);\n} catch (e) {\n  if (e instanceof EmptyResultError) return [];\n  throw e;\n}","preventionTips":["Verify the destination exists on trip.com (via POI search) before tour search.","Try both tour types when a market may lack one.","Catch EmptyResultError and return an empty list instead of failing the workflow.","Keep a list of destinations known to have zero tour inventory."],"tags":["empty-result","tours","trip-com"],"backgroundTag":"empty-search-results","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}